基於 uni-app 實現動態路由和動態 Tabbar

本文轉載自 字節逆旅 公衆號,感謝做者的好文分享✌️,點擊閱讀原文能夠查看做者的掘金連接。html

uniapp用來開發app仍是比較方便快捷的,官網教程[1]挺細緻,幾乎全部問題都能找到答案。網上也有很多入門教程,騰訊課堂、b站上有好幾個視頻教程,感受還能夠(其實我沒怎麼看),比較偏實戰,能夠動手試一下。前端

本文假設閱讀者已經基本掌握了uniapp的入門開發技能,若是尚未掌握uniapp,但你準備進行相關開發,趕忙從官方文檔入手,再結合實戰視頻操做就行了,前面推薦的都不錯。好了,進入本文主題——如何基於uniapp框架實現動態路由、動態tabbarvue

現狀分析

vue項目上有路由插件Vue Router,全部路由都是統一管理,能夠統一攔截,控制下一步動做,可是在uniapp上,狀況就不同了。uniapp上沒有路由插件,而後頁面分爲tabbar和非tabbar兩種,頁面跳轉也有本身的一套api,最重要的路由攔截功能並不支持,全部的頁面都是在page.json文件裏提早配置好。web

需求分析

那假設咱們要在app上作一套對應着用戶權限的東西,就是不一樣用戶,根據權限配置,決定了他進來後能用哪些頁面哪些按鈕,甚至是能控制到tabbar這塊。這個需求,就須要根據權限控制路由內容及導向,但在目前條件下是實現不了的。不過在插件市場有很多人寫了路由插件,思路其實都是向web端的vue Router看齊的,能完整知足需求的只有這個路由插件[2]vue-router

還有很重要的一個需求就是動態tabbar,這是一個很重要內容,就是在app登陸後主頁下面的一欄按鈕,這些tabbar基本上包括了app的主要內容,如何實現動態的tabbar,像上面提到的根據權限控制。好比說tabbar最多隻能有五個,那我如何控制甲能看到5個,乙只能看到3個?這個需求在原生的uniapp上沒法實現,原生的只能配置好pages,tabBar是pages的一個子項配置。不過插件市場上有人實現了tabbar的組件化,咱們能夠嘗試下定製開發。vuex

總結起來講需求其實就兩個:npm

一、實現uniapp路由守衛;json

二、實現動態tabbar;小程序

第一個需求,前面提到過一些方案;第二個需求,動態tabbar,須要結合uview組件庫[3]tabbar[4]組件來實現。咱們再分析下目前的框架、插件能力,糅合上述需求,就有這張圖:api

這張圖裏有些內容前面沒有提到,好比狀態管理、本地緩存,這是後面會用到的一個關鍵部分,下面的設計部分會提到。

方案設計

咱們來捋一捋業務流程設計:

一、app輸入用戶名密碼登陸;

二、在路由守衛進行攔截,判斷用戶登陸時的本地數據是否存在路由信息;若是沒有則走第3步,若是有就走第4步;

三、調用接口獲取到路由並從服務端獲取路由數據;將路由數據存入本地(vuex、uniapp緩存);

四、將tabbar這一層級數據單獨提出來存儲,結合uview的tabbar組件實現動態tabbar;

五、在本地存一個全量的app按鈕集合(除了tabbar,其餘頁面都是經過按鈕跳轉),與服務端獲取的數據進行比對,獲得一個按鈕展現與否的配置數據集;

六、路由信息初始化後,進入用戶定製化的初始頁或者首頁;

ok,分析得差很少了,下面介紹下具體實操步驟。

解決方案

1、實現路由守衛

路由插件推薦uni-simple-router,具體教程能夠參考它的官方文檔[5],寫得比較詳細了。如下是個人簡單實戰教程。

安裝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: {
  holdTabbarfalse //默認true
 },
 h5: {
  vueRouterDevtrue//徹底使用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,後者請慎用。

2、結合狀態管理、uniapp數據緩存管理app緩存開銷

這裏其實沒什麼難度,也不給代碼了,很簡單。

從服務端獲取的數據我能夠存在狀態管理裏,可是vuex的數據存在內存中,容易丟失。好比說,app用一下子,我拉到了後臺,立馬再點開是沒問題能夠用的;但若是時間太長了,不當心清了緩存,或者超過了服務端的超時限制,此時再次點開app,可能就缺失了部分數據。這個問題就要在路由守衛進行處理了,在路由跳轉時就判斷相關的狀態數據是否存在,不存在就再進行處理。

再介紹一下uniapp的數據緩存api,更穩定,特別在app上,它不是緩存的概念,是持久化存在的,除非你調用它的清除方法。你能夠利用這兩者,分別存一些數據,搭配作一些控制,具體實現就本身琢磨下。好比你從後臺拉回,狀態管理的數據沒了,但這個時間還在服務端超時範圍內,那這個未超時的token數據就要存在uniapp的數據緩存中,我根據這個token再查到相關權限路由信息,給vuex賦值,再進行後續操做;若是拉回來,超時了,那就直接回到登陸頁。這一塊,我只是提供思路,並且是成功的思路,親測有效的。

3、實現動態tabbar

好了,能走到這一步,萬里長征就走了一半了。別看下面的內容就那麼一點,我把相關的資料拼起來實際上花了比上面那些更多的時間。

因爲tabbar是單獨配置的,原生的uniapp沒有動態配置的方法。找了一圈,發現uview的tabbar組件能夠實現。這塊仍是把步驟列一下:一步步來,是能夠實現的!

一、修改pages.json配置
"tabBar": {
  "list": [{
   "pagePath""pages/index/index"
  },{
   "pagePath""pages/about/about"
  }]
 },

像這樣,只留這些內容,跟原生配置比少了許多內容。

二、將tabbar信息單獨存儲到一個全局對象上

這一步能夠存在vuex裏,由於讀取方便,uniapp的數據緩存讀取稍微麻煩點。放在vuex裏,取的時候很方便,像這樣:

this.$store.state.userInfo.tabbarlist
三、在每個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與正文內容並列;跳轉代碼以下,兩種方式都是能夠的,詳細見文檔[6]

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的完整方案講清楚了,細節部分本身順着個人思路,根據你本身的須要,逐步完善便可,但願對你會有啓發和幫助。若是對你有用,請點擊在看分享,謝謝!

參考資料

[1]

官網教程: https://uniapp.dcloud.io/quickstart

[2]

路由插件: http://hhyang.cn/src/router/start/quickstart.html

[3]

uview組件庫: http://uviewui.com/components/intro.html

[4]

tabbar: http://uviewui.com/components/tabbar.html

[5]

官方文檔: http://hhyang.cn/src/router/start/quickstart.html

[6]

文檔: http://hhyang.cn/src/router/start/cross/codeRoute.html

- END -
   

● 前端科普系列(一):前端發展簡史

● 你不知道的 Npm(Node.js 進階必備好文)

● 用動畫和實戰打開 React Hooks(一):useState 和 useEffect



·END·

圖雀社區

匯聚精彩的免費實戰教程



關注公衆號回覆 z 拉學習交流羣


喜歡本文,點個「在看」告訴我

本文分享自微信公衆號 - 圖雀社區(tuture-dev)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。

相關文章
相關標籤/搜索