如何基于uniapp框架實現動態路由、動態tabbar?本篇文章就來給大家介紹一下uniapp動態路由實戰,手把手教大家在uniapp中實現動態路由。
uniapp用來開發app還是比較方便快捷的,官網教程挺細致,幾乎所有問題都能找到答案。網上也有不少入門教程,騰訊課堂、b站上有好幾個視頻教程,感覺還可以(其實我沒怎么看),比較偏實戰,可以動手試一下。
本文假設閱讀者已經基本掌握了uniapp的入門開發技能,如果還沒有掌握uniapp,但你準備進行相關開發,趕緊從官方文檔入手,再結合實戰視頻操作就好了,前面推薦的都不錯。好了,進入本文主題——如何基于uniapp框架實現動態路由、動態tabbar。
現狀分析
vue項目上有路由插件Vue Router,所有路由都是統一管理,可以統一攔截,控制下一步動作,但是在uniapp上,情況就不一樣了。uniapp上沒有路由插件,然后頁面分為tabbar和非tabbar兩種,頁面跳轉也有自己的一套api,最重要的路由攔截功能并不支持,所有的頁面都是在page.json文件里提前配置好。
需求分析
那假設我們要在app上做一套對應著用戶權限的東西,就是不同用戶,根據權限配置,決定了他進來后能用哪些頁面哪些按鈕,甚至是能控制到tabbar這塊。這個需求,就需要根據權限控制路由內容及導向,但在目前條件下是實現不了的。不過在插件市場有不少人寫了路由插件,思路其實都是向web端的vue Router看齊的,能完整滿足需求的只有這個路由插件。
還有很重要的一個需求就是動態tabbar,這是一個很重要內容,就是在app登錄后主頁下面的一欄按鈕,這些tabbar基本上包括了app的主要內容,如何實現動態的tabbar,像上面提到的根據權限控制。比如說tabbar最多只能有五個,那我如何控制甲能看到5個,乙只能看到3個?這個需求在原生的uniapp上無法實現,原生的只能配置好pages,tabBar是pages的一個子項配置。不過插件市場上有人實現了tabbar的組件化,我們可以嘗試下定制開發。
總結起來說需求其實就兩個:
1、實現uniapp路由守衛;
2、實現動態tabbar;
第一個需求,前面提到過一些方案;第二個需求,動態tabbar,需要結合uview組件庫的tabbar組件來實現。我們再分析下目前的框架、插件能力,糅合上述需求,就有這張圖:
這張圖里有些內容前面沒有提到,比如狀態管理、本地緩存,這是后面會用到的一個關鍵部分,下面的設計部分會提到。
方案設計
我們來捋一捋業務流程設計:
1、app輸入用戶名密碼登錄;
2、在路由守衛進行攔截,判斷用戶登錄時的本地數據是否存在路由信息;如果沒有則走第3步,如果有就走第4步;
3、調用接口獲取到路由并從服務端獲取路由數據;將路由數據存入本地(vuex、uniapp緩存);
4、將tabbar這一層級數據單獨提出來存儲,結合uview的tabbar組件實現動態tabbar;
5、在本地存一個全量的app按鈕集合(除了tabbar,其他頁面都是通過按鈕跳轉),與服務端獲取的數據進行比對,得到一個按鈕展示與否的配置數據集;
6、路由信息初始化后,進入用戶定制化的初始頁或者首頁;
ok,分析得差不多了,下面介紹下具體實操步驟。
解決方案
一、實現路由守衛
路由插件推薦uni-simple-router,具體教程可以參考它的官方文檔,寫得比較詳細了。以下是我的簡單實戰教程。
安裝uni-simple-router插件
npm install uni-simple-router
接下來進行模塊化配置,創建文件夾router,文件夾內容如下:
home文件里是所有頁面的路由配置,就像這樣:
const home = [ { path: '/pages/login/login', aliasPath:'/app/login', //對于h5端適用 name: 'login', meta: { title: '登錄', } }, { path: '/pages/index/index', aliasPath:'/app/index', //對于h5端適用 name: 'index', meta: { title: '首頁', } }] export default home
這里必須要多說一句,由于這個插件沒有動態寫入功能,所以我們要實現權限管理,必須在本地配置完整的路由;而且pages.json中的內容也要完整配置,不過tabbar配置有些不同,后面會說到;
modules文件夾下的index只是一個模塊讀取的代碼;
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
router根級目錄下的index內容主要就是路由守衛:
import modules from './modules/index.js' import Vue from 'vue' import Router from 'uni-simple-router' import store from '@/store/store.js' Vue.use(Router) //初始化 const router = new Router({ APP: { holdTabbar: false //默認true }, h5: { vueRouterDev: true, //完全使用vue-router開發 默認 false }, routes: [...modules] //路由表 }); //全局路由前置守衛 router.beforeEach((to, from, next) => { // 首先判斷是否存在路由信息 //不存在就先調用接口得到數據 //具體內容可以參照上文的方案設計內容 }) // 全局路由后置守衛 router.afterEach((to, from) => {}) export default router;
最后在app的main.js里需要這么引用:
import router from './router/index.js' import { RouterMount } from 'uni-simple-router' ... //v1.3.5起 H5端 你應該去除原有的app.$mount();使用路由自帶的渲染方式 // #ifdef H5 RouterMount(app,'#app'); // #endif //為了兼容小程序及app端必須這樣寫才有效果 // #ifndef H5 app.$mount(); // #endif
至于后面的路由用法,直接看官方文檔,比較清楚,用法跟vue-router差不多。這里要特別說明的是上面代碼初始化的那一塊的幾個配置:holdTabbar: false,vueRouterDev: true,前者表示在app端取代原生的tabbar攔截,在這個插件里攔截;后者表示在h5中完全用vue-router的api,廢棄了包括此插件及uniapp的原生api,后者請慎用。
二、結合狀態管理、uniapp數據緩存管理app緩存開銷
這里其實沒什么難度,也不給代碼了,很簡單。
從服務端獲取的數據我可以存在狀態管理里,但是vuex的數據存在內存中,容易丟失。比如說,app用一會兒,我拉到了后臺,立馬再點開是沒問題可以用的;但如果時間太長了,不小心清了緩存,或者超過了服務端的超時限制,此時再次點開app,可能就缺失了部分數據。這個問題就要在路由守衛進行處理了,在路由跳轉時就判斷相關的狀態數據是否存在,不存在就再進行處理。
再介紹一下uniapp的數據緩存api,更穩定,特別在app上,它不是緩存的概念,是持久化存在的,除非你調用它的清除方法。你可以利用這二者,分別存一些數據,搭配做一些控制,具體實現就自己琢磨下。比如你從后臺拉回,狀態管理的數據沒了,但這個時間還在服務端超時范圍內,那這個未超時的token數據就要存在uniapp的數據緩存中,我根據這個token再查到相關權限路由信息,給vuex賦值,再進行后續操作;如果拉回來,超時了,那就直接回到登錄頁。這一塊,我只是提供思路,而且是成功的思路,親測有效的。
三、實現動態tabbar
好了,能走到這一步,萬里長征就走了一半了。別看下面的內容就那么一點,我把相關的資料拼起來實際上花了比上面那些更多的時間。
由于tabbar是單獨配置的,原生的uniapp沒有動態配置的方法。找了一圈,發現uview的tabbar組件可以實現。這塊還是把步驟列一下:一步步來,是可以實現的!
1、修改pages.json配置
"tabBar": { "list": [{ "pagePath": "pages/index/index" },{ "pagePath": "pages/about/about" }] },
像這樣,只留這些內容,跟原生配置比少了許多內容。
2、將tabbar信息單獨存儲到一個全局對象上
這一步可以存在vuex里,因為讀取方便,uniapp的數據緩存讀取稍微麻煩點。放在vuex里,取的時候很方便,像這樣:
this.$store.state.userInfo.tabbarlist
3、在每一個tabbar頁面配置tabbar組件
<template> <view> <view class="content"> ... </view> <u-tabbar :list="$store.state.userInfo.tabbarlist" @change="changeTb" :inactive-color="inactiveColor" :active-color="activeColor"></u-tabbar> </view> </template>
模板部分格式要像上面這樣,tabbar與正文內容并列;跳轉代碼如下,兩種方式都是可以的,詳細見文檔
changeTb(index) { // uni.switchTab({ // url: this.$store.state.userInfo.tabbarlist[index].pagePath // }); this.$Router.pushTab(this.$store.state.userInfo.tabbarlist[index].pagePath) }
需要說明的是,這種方法是把uniapp的原生tabbar給隱藏了的;上面用到的狀態管理中的tabbarlist數據是一個結構參數完整的tabbar配置,但是tabbar頁面可能不是完整的,由用戶權限決定。
好了,本文到此已經把動態路由、動態tabbar的完整方案講清楚了,細節部分自己順著我的思路,根據你自己的需要,逐步完善即可,希望對你會有啟發和幫助。如果對你有用,請點擊在看分享,謝謝!