• 技术文章 >web前端 >uni-app

    手把手教你基于uniapp框架实现动态路由、动态tabbar

    青灯夜游青灯夜游2021-08-27 19:10:32转载257
    如何基于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.png

    这张图里有些内容前面没有提到,比如状态管理、本地缓存,这是后面会用到的一个关键部分,下面的设计部分会提到。

    方案设计

    我们来捋一捋业务流程设计:

    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,文件夹内容如下:

    2.png

    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的完整方案讲清楚了,细节部分自己顺着我的思路,根据你自己的需要,逐步完善即可,希望对你会有启发和帮助。如果对你有用,请点击在看分享,谢谢!

    推荐:《uniapp教程

    以上就是手把手教你基于uniapp框架实现动态路由、动态tabbar的详细内容,更多请关注php中文网其它相关文章!

    声明:本文转载于:掘金社区,如有侵犯,请联系admin@php.cn删除
    专题推荐:uniapp 动态路由
    上一篇:什么是render.js?UNiAPP中怎么使用它来绘制高德地图? 下一篇:uniapp适配到微信小程序需要注意些什么?
    线上培训班

    相关文章推荐

    • uniapp怎么改变checkbox选中状态• Uniapp发布为H5版本时如何隐藏访问路径的#符号• 如何优化uniapp项目?分享几种优化方案及建议• 什么是render.js?UNiAPP中怎么使用它来绘制高德地图?

    全部评论我要评论

  • 取消发布评论发送
  • 1/1

    PHP中文网