基于 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源创计划”,欢迎正在阅读的你也加入,一块儿分享。

相关文章
相关标签/搜索