快速上手uni-simple-router
uni-simple-router
- 專為uniapp打造的路由器,和uniapp深度集成
- 通配小程序、App和H5端
- H5能完全使用vue-router開(kāi)發(fā)
- 模塊化、查詢、通配符、路由參數(shù)
- 使 uni-app實(shí)現(xiàn)嵌套路由(僅H5端完全使用vue-router)
- uniapp用到了很多vue的api,但在路由管理的功能相對(duì)于vue-router還是比較欠缺的,比如全局導(dǎo)航守衛(wèi)
官方文檔:https://hhyang.cn/v2/start/quickstart.html
一、快速上手
// 針對(duì)uniapp HBuilder創(chuàng)建的項(xiàng)目,非cli構(gòu)建 // 1? NPM 安裝 npm install uni-simple-router // 2? 初始化 npm install uni-read-pages // 配合vue.config.js自動(dòng)讀取pages.json作為路由表的方式,源碼例如下:擴(kuò)二 // 配置vue.config.js const TransformPages = require('uni-read-pages') const tfPages = new TransformPages() module.exports = { configureWebpack: { plugins: [ new tfPages.webpack.DefinePlugin({ // 1? 配置全局變量 // ROUTES: JSON.stringify(tfPages.routes) // 2? includes 可自定義,解析pages.json路由配字段的配置, 默認(rèn) ['path', 'name', 'aliasPath'] ROUTES: tfPages.webpack.DefinePlugin.runtimeValue(()=>{ const tf = new TransformPages({ includes: ['path', 'name', 'aliasPath'] }) return JSON.stringify(tfPages.routes) },true) }) ] } } // /Applications/HBuilderX.app/Contents/HBuilderX/plugins/uniapp-cli/node_modules/webpack 我的webpack包路徑,在軟件contents包文件里軟件自帶的webpack
擴(kuò)一:webpack插件之DefinePlugin
- 允許創(chuàng)建一個(gè) 在編譯時(shí)可以配置的全局變量
- 場(chǎng)景:區(qū)分不同開(kāi)發(fā)模式處理
// 1? 用法:每個(gè)傳進(jìn)DefinePlugin的鍵值都是一個(gè)標(biāo)志或者多個(gè)用.連接起來(lái)的標(biāo)識(shí)符 new webpack.DefinePlugin({ PRODUCTION: JSON.stringify(true), BROWSER_SUPPRTS_HTML5: true, VERSION: JSON.stringify('abcde'), TWO: '1+1', 'typeof window': JSON.stringify('object') }) // 使用方式 console.log('Running App version', VERSION) if(!BROWSER_SUPPRTS_HTML5) require("html5shiv") // 2? 功能標(biāo)記 來(lái)作為一個(gè)flag標(biāo)識(shí)啟用和禁用構(gòu)建中的功能 new webpack.DefinePlugin({ 'SHOW_PRESSION': JOSN.string(true) }) // 3? 服務(wù):可以配置不同環(huán)境下的url new webpack.DefinePlugin({ 'DEV_URL': JSON.stringify(url_dev), 'PRO_URL': JSON.stringify(url_pro) })
擴(kuò)二:uni-read-pages 如何獲取pages.json中的路由
// 依賴的源碼 - 通過(guò)node的path模塊獲取pages.json文件中的任何信息 (部分是個(gè)人注釋) const path = require('path') const CONFIG = { includes: ['path', 'aliasPath', 'name'] } // 默認(rèn)獲取路由參數(shù)屬性 // process.cwd() 返回Node.js進(jìn)程的當(dāng)前工作目錄 // path.resolve(url1, 'abc') => url1/abc const rootPath = path.resolve(process.cwd(), 'node_modules'); // 獲取根路徑 /** 解析絕對(duì)路徑 * @param {Object} dir */ function resolvePath(dir) { return path.resolve(rootPath, dir); } // 類 class TransformPages { constructor(config) { // 組合 自定義獲取配置屬性 config = { ...CONFIG, ...config }; this.CONFIG = config; // ↓本機(jī)文件路徑(HBuilderX包文件里自帶的webpack模塊路徑) /Applications/HBuilderX.app/Contents/HBuilderX/plugins/uniapp-cli/node_modules/webpack this.webpack = require(resolvePath('webpack')); this.uniPagesJSON = require(resolvePath('@dcloudio/uni-cli-shared/lib/pages.js')); // TODO: 根據(jù)CONFIG解析pages.json中的路由信息 和 小程序 分包下的路由 this.routes = this.getPagesRoutes().concat(this.getNotMpRoutes()); } // 獲取所有pages.json下的內(nèi)容 返回json get pagesJson() { return this.uniPagesJSON.getPagesJson(); } // 通過(guò)讀取pages.json文件 生成直接可用的routes getPagesRoutes(pages = this.pagesJson.pages, rootPath = null) { const routes = []; for (let i = 0; i < pages.length; i++) { const item = pages[i]; const route = {}; for (let j = 0; j < this.CONFIG.includes.length; j++) { const key = this.CONFIG.includes[j]; let value = item[key]; if (key === 'path') { value = rootPath ? `/${rootPath}/${value}` : `/${value}` } if (key === 'aliasPath' && i == 0 && rootPath == null) { route[key] = route[key] || '/' } else if (value !== undefined) { route[key] = value; } } routes.push(route); } return routes; } // 解析小程序分包路徑 getNotMpRoutes() { const { subPackages } = this.pagesJson; let routes = []; if (subPackages == null || subPackages.length == 0) { return []; } for (let i = 0; i < subPackages.length; i++) { const subPages = subPackages[i].pages; const root = subPackages[i].root; const subRoutes = this.getPagesRoutes(subPages, root); routes = routes.concat(subRoutes) } return routes } /** * 單條page對(duì)象解析 * @param {Object} pageCallback * @param {Object} subPageCallback */ parsePages(pageCallback, subPageCallback) { this.uniPagesJSON.parsePages(this.pagesJson, pageCallback, subPageCallback) } } module.exports = TransformPages
二、H5模式
2.1 路由配置
import {RouterMount,createRouter} from 'uni-simple-router'; const router = createRouter({ // 路由配置 routes: [ { path: '/pages/index/index', // 必須和pages.json中相同 extra: { pageStyle: { color: '#f00' }// 及其它自定義參數(shù) } } ] }) // 組件中可以通過(guò) this.$Route 查看路由元信息
2.2 完全使用vue-router開(kāi)發(fā) (H5端)
- 嵌套路由時(shí),若使用name方式跳轉(zhuǎn),僅支持 this.$router.push({ name: children1 })
// 使用 vue-router開(kāi)發(fā)將會(huì)失去uniapp的生命周期 const router = createRouter({ h5: { vueRouterDev: true, // 完全使用vue-router開(kāi)發(fā) 默認(rèn)是false }, // 路由配置 routes: [ { path: '/', name: 'home', component: () => import('@/common/router/home.vue'), // 嵌套路由(僅H5端),小程序端會(huì)重新頁(yè)面打開(kāi) children: [ { path: 'home/children1', name: 'children1', component: () => import('@/common/router/children1.vue') }, { path: 'home/children2', name: 'children2', component: () => import('@/common/router/children2.vue') } ] } ] })
2.3 H5 路由傳參
// 除vue-router外,美化url可以在基礎(chǔ)配置時(shí),定義aliasPath變量,設(shè)置路由別名(瀏覽器地址欄展示名稱) // 別名的設(shè)置,如果設(shè)置了別名,通過(guò)push路徑的方式,必須使用aliasPath的路徑才能生效 const router = createRouter({ routes:[{ name:'router1', //為了兼容其他端,此時(shí)的path不能少,必須和 pages.json中的頁(yè)面路徑匹配 path: "/pages/tabbar/tabbar-1/tabbar-1", aliasPath: '/tabbar-1', },] }); // uni-simple-router路由跳轉(zhuǎn) // aliasPath命名的路由 => name傳遞參數(shù)需 params this.$Router.push({ name: 'detail', params: { id: 1 } }) // 帶查詢參數(shù),變成 /home/id=1 => path 對(duì)應(yīng)query,params失效 this.$Router.push({ path: '/pages/index/detail', query: { id: 1 }})
2.4 H5端路由捕獲所有路由或404路由
path:'*' // 通常用于客戶端404錯(cuò)誤,如果是history模式,需要正確配置服務(wù)器 path: '/detail-*' // 路由的優(yōu)先級(jí)根據(jù) 定義的先后
2.5 路由懶加載
打包構(gòu)建應(yīng)用時(shí),Javascript包會(huì)變得非常大,影響頁(yè)面加載,把不同路由對(duì)應(yīng)的組件分割成不同的代碼塊,然后當(dāng)路由被訪問(wèn)的時(shí)候才加載對(duì)應(yīng)組件。
const Foo = () => import('./Foo.vue') // 把組件按組分塊 使用 命名 chunk const Foo = () => import(/*webpackChunkName:"group-foo"*/ './Foo.vue') const Bar = () => import(/*webpackChunkName:"group-foo"*/ './Bar.vue')
三、小程序模式
注:小程序系列無(wú)法攔截原生tabbar及原生導(dǎo)航返回,如需攔截使用自定義tabbar、header
通過(guò)api進(jìn)行切換時(shí),像uni.switchTab()和this.$Router.pushTab()方法會(huì)觸發(fā)攔截的;僅底部原生tabbar進(jìn)行切換時(shí)不觸發(fā)攔截
強(qiáng)制觸發(fā)守衛(wèi):forceGuardEach(replaceAll, false) 每次調(diào)用api都會(huì)重新按流程觸發(fā)已經(jīng)聲明的所有守衛(wèi)
- 小程序端默認(rèn):插件api跳轉(zhuǎn)、uni導(dǎo)航api跳轉(zhuǎn)和首屏加載
- 使用路由守衛(wèi):通過(guò)點(diǎn)擊事件強(qiáng)制觸發(fā)、混入到onshow回調(diào)觸發(fā)
跳轉(zhuǎn)路由鎖:animationDuration保留給redirection\push足夠時(shí)間,等切換完成頁(yè)面后才放行下次跳轉(zhuǎn)
const router = createRouter({ platform: process.env.VUE_APP_PLATFORM, // ① 路由鎖 applet: { animationDuration: 300 // 默認(rèn)300ms // animationDuration: 0 // 不精準(zhǔn) 只捕捉跳轉(zhuǎn)api下的complete函數(shù) }, // ②優(yōu)雅解鎖 error.type: 0 表示 next(false)、1表示next(unknownType)、2表示加鎖狀態(tài),禁止跳轉(zhuǎn)、3表示在獲取頁(yè)面棧時(shí),頁(yè)面棧不夠level獲取 routerErrorEach:(error, router) => { if (error.type === 3) { router.$lockStatus = false } }, routes: [...ROUTES] })
四、路由跳轉(zhuǎn)
4.1 組件跳轉(zhuǎn)
vue-router中可以通過(guò)router-link組件進(jìn)行頁(yè)面跳轉(zhuǎn),uni-simple-router也提供了類似的組件,需要手動(dòng)注冊(cè)
// main.js import Link from './node_modules/uni-simple-router/dist/link.vue' Vue.component('Link', Link)
// 通過(guò)path直接跳轉(zhuǎn) 并指定跳轉(zhuǎn)類型 <Link to="/tabbar1" navType="pushTab"> <button type="primary">使用path對(duì)象跳轉(zhuǎn)</button> </Link>
4.2 編程式導(dǎo)航
- 通過(guò)this.$Router獲取路由對(duì)象;push、pushTab、replace、back等api進(jìn)行路由跳轉(zhuǎn)
- 注:path搭配query參數(shù)、name搭配params參數(shù)
- 導(dǎo)航使用方式同vue-router
五、跨平臺(tái)模式
5.1 提前享用生命周期
uniapp由于只用onLoad接受options參數(shù)、onShow不接受;傳遞深度對(duì)象參數(shù)時(shí),需要先編碼再傳遞解碼
// 動(dòng)態(tài)改變參數(shù) 使 onLoad和onShow支持options const router = createRouter({ platform: process.env.VUE_APP_PLATFORM, routes: [...ROUTES], beforeProxyHooks: { onLoad(options, next){ next([router.currentRoute.query]); }, onShow([options], next){ console.log(this); const args=options||router.currentRoute.query; next([args]); }, }, });
5.2 導(dǎo)航守衛(wèi)
全局前置守衛(wèi)
/** * to: Route 即將進(jìn)入的目標(biāo) * from: Route 當(dāng)前導(dǎo)航正要離開(kāi)的路由 * next: Function 該方法的resolve鉤子函數(shù)必須調(diào)用,執(zhí)行效果依賴next方法的調(diào)用參數(shù) * -- next()調(diào)用參數(shù):管道中的下個(gè)鉤子; next(false)中斷當(dāng)前導(dǎo)航; * -- next('/')/({path: '/'})跳轉(zhuǎn)到一個(gè)不同的地址。當(dāng)前的導(dǎo)航被中斷,然后進(jìn)行一個(gè)新的導(dǎo)航 * -- next({delta: 2, NAVTYPE: 'back'}) 中斷當(dāng)前導(dǎo)航,調(diào)用新的跳轉(zhuǎn)類型,同時(shí)返回兩層頁(yè)面 **/ router.beforeEach((to, from, next) => { // ... // 1? next() // 2? NAVTYPE定義跳轉(zhuǎn)方式,兩者相同非必填 if (to.name == 'tabbar-5') { next({ name: 'router4', params: { msg: '我攔截了tab5并重定向到了路由4頁(yè)面上', }, NAVTYPE: 'push' }); } else{ next(); } })
全局后置守衛(wèi)
// 不接受next函數(shù)也不改變導(dǎo)航本身 router.afterEach((to,from) => {})
路由獨(dú)享守衛(wèi)
// 路由配置上直接定義beforeEnter守衛(wèi) const router = createRouter({ routes: [{ path: '/pages/home/index', beforeEnter:(to,from,next) => { // 參數(shù)同上全局前置守衛(wèi) next() } }] })
組件內(nèi)的守衛(wèi)
// 組件內(nèi)配置beforeRouteLeave守衛(wèi) - 直接調(diào)用beforeRouteLeave方法 export default { beforeRouteLeave(to, from, next) { // 導(dǎo)航離開(kāi)該組件的對(duì)應(yīng)路由時(shí)調(diào)用 // 可以訪問(wèn)組件實(shí)例this next() } }
六、路由守衛(wèi)-模塊化
// 1? 創(chuàng)建 router文件夾,模塊化配置 文件結(jié)構(gòu) |+------------------------+| | router | | |+--------------------+| | | | modules | | | | |+----------------+| | | | | | home.js | | | | | | index.js | | | | | |+----------------+| | | | |+--------------------+| | | index.js | |+------------------------+|
// home.js const home = [ { path: '/pages/home/index', name: 'home' } ] export default home
// modules下的index.js是一個(gè)模塊讀取 // ① require.context(directory, useSubdirectories, regExp) 具體詳情:如下擴(kuò)三 const files = require.context('.',false,/.js$/) const modules = [] files.keys().forEach(key => { if (key === './index.js') return const item = files(key).default modules.push(...item) }) export default modules // 將所有模塊的路由模塊整合到一起, routes Array
// router下的index.js 路由守衛(wèi) import modules from './modules/index.js' import Vue from 'vue' import CreateRouter from 'uni-simple-router' import store from '@/store/store.js' Vue.use(CreateRouter) //初始化 const router = new CreateRouter({ APP: { holdTabbar: false //默認(rèn)true }, h5: { vueRouterDev: true, //完全使用vue-router開(kāi)發(fā) 默認(rèn) false }, // 也可以 通過(guò)uni-read-pages來(lái)讀取pages.json文件的路由表,配合vue.config.js // router: [...ROUTES] // ROUTES是通過(guò)webpack的defaultPlugin編譯成全局變量,具體操作上文 routes: [...modules] //路由表 }); //全局路由前置守衛(wèi) router.beforeEach((to, from, next) => { // 首先判斷是否存在路由信息 //不存在就先調(diào)用接口得到數(shù)據(jù) }) // 全局路由后置守衛(wèi) router.afterEach((to, from) => {}) export default router;
擴(kuò)三、require.context用法
// require.context(directory, useSubdirectories, regExp) // directory: 表示檢索的目錄 // useSubdirectories: 表示是否檢索子文件夾 // regExp: 匹配文件的正則表達(dá)式 // 返回值: resolve是一個(gè)函數(shù),返回已解析請(qǐng)求的模塊ID; keys是一個(gè)函數(shù),它返回上下文模塊可以處理的所有可能請(qǐng)求的數(shù)組; // 使用場(chǎng)景:①用來(lái)組件內(nèi)引入多個(gè)組件;②在main.js內(nèi)引入大量公共組件;
// ①組件內(nèi)引入多個(gè)組件 - webpack const path = require('path') const files = require.context('@/components/home', false, /\.vue$/) //值類型 ['./home.js', 'detail.js',...] const modules = {} files.keys().forEach(key => { const name = paths.basename(key, '.vue') // 去掉文件名的 .vue后綴 modules[name] = files(key).default || files(key) }) // modules { home: '{module樣式路徑}', detail: '{}', ... } export default { ..., data() { return {}}, components: modules }
// ②在main.js內(nèi)引入大量公共組件 import Vue from 'vue' // 引入自定義組件 const requireComponents = require.context('../views/components',true,'/\.vue/') // 遍歷出每個(gè)數(shù)組的路徑 requireComponents.keys().forEach(fileName => { const reqCom = requireComponents(fileName) // 獲取組件名 const reqComName = reqCom.name || fileName.replace(/\.\/(.*)\.vue/, '$1') // 組件掛載 Vue.components(reqComName, reqCom.default || reqCom) })
到此這篇關(guān)于uni-simple-router的文章就介紹到這了,更多相關(guān)uni-simple-router內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
JS笛卡爾積算法與多重?cái)?shù)組笛卡爾積實(shí)現(xiàn)方法示例
這篇文章主要介紹了JS笛卡爾積算法與多重?cái)?shù)組笛卡爾積實(shí)現(xiàn)方法,結(jié)合實(shí)例形式分析了javascript根據(jù)對(duì)象或數(shù)組生成笛卡爾積的相關(guān)操作技巧,需要的朋友可以參考下2017-12-12JS實(shí)現(xiàn)table表格內(nèi)針對(duì)某列內(nèi)容進(jìn)行即時(shí)搜索篩選功能
這篇文章主要介紹了JS實(shí)現(xiàn)table表格內(nèi)針對(duì)某列內(nèi)容進(jìn)行即時(shí)搜索篩選功能,涉及javascript針對(duì)HTML元素的遍歷、屬性動(dòng)態(tài)修改相關(guān)操作技巧,需要的朋友可以參考下2018-05-05JS檢測(cè)window.open打開(kāi)的窗口是否關(guān)閉
在開(kāi)發(fā)中遇到需要在打開(kāi)窗口的同時(shí)給父窗口添加遮罩防止用戶誤操作,而在窗口關(guān)閉時(shí)需要去掉父窗口的遮罩以便用戶操作。所以可以利用setInterval()來(lái)周期性的檢測(cè)打開(kāi)的窗口是否關(guān)閉2017-06-06JS回調(diào)函數(shù)原理與用法詳解【附PHP回調(diào)函數(shù)】
這篇文章主要介紹了JS回調(diào)函數(shù)原理與用法,結(jié)合實(shí)例形式詳細(xì)分析了JavaScript回調(diào)函數(shù)的概念、原理、用法,并給出了PHP回調(diào)函數(shù)的使用示例,需要的朋友可以參考下2019-07-07Js實(shí)現(xiàn)兩個(gè)跨域頁(yè)面進(jìn)行跳轉(zhuǎn)傳參的方案詳解
這篇文章主要為大家詳細(xì)介紹了JavaScript中實(shí)現(xiàn)兩個(gè)跨域頁(yè)面進(jìn)行跳轉(zhuǎn)傳參的方案,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2023-12-12認(rèn)識(shí)less和webstrom的less配置方法
下面小編就為大家?guī)?lái)一篇認(rèn)識(shí)less和webstrom的less配置方法。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-08-08JavaScript實(shí)現(xiàn)伸縮二級(jí)菜單
這篇文章主要為大家詳細(xì)介紹了JavaScript實(shí)現(xiàn)伸縮二級(jí)菜單,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-10-10JS簡(jiǎn)單編號(hào)生成器實(shí)現(xiàn)方法(附demo源碼下載)
這篇文章主要介紹了JS簡(jiǎn)單編號(hào)生成器實(shí)現(xiàn)方法,涉及JavaScript針對(duì)表單與字符串操作的相關(guān)技巧,并附帶demo源碼供讀者下載參考,需要的朋友可以參考下2016-04-04js+css 實(shí)現(xiàn)遮罩居中彈出層(隨瀏覽器窗口滾動(dòng)條滾動(dòng))
本文為大家詳細(xì)介紹下使用js實(shí)現(xiàn)遮罩彈出層居中,且隨瀏覽器窗口滾動(dòng)條滾動(dòng),示例代碼如下,感興趣的朋友可以參考下2013-12-12