vue项目上有路由插件VueRouter,所有路由都是统一管理,可以统一拦截,控制下一步动作,但是在uniapp上,情况就不一样了。uniapp上没有路由插件,然后页面分为tabbar和非tabbar两种,页面跳转也有自己的一套api,最重要的路由拦截功能并不支持,所有的页面都是在page.json文件里提前配置好。
总结起来说需求其实就两个:
1、实现uniapp路由守卫;
2、实现动态tabbar;
这张图里有些内容前面没有提到,比如状态管理、本地缓存,这是后面会用到的一个关键部分,下面的设计部分会提到。
我们来捋一捋业务流程设计:
3、调用接口获取到路由并从服务端获取路由数据;将路由数据存入本地(vuex、uniapp缓存);
4、将tabbar这一层级数据单独提出来存储,结合uview的tabbar组件实现动态tabbar;
5、在本地存一个全量的app按钮集合(除了tabbar,其他页面都是通过按钮跳转),与服务端获取的数据进行比对,得到一个按钮展示与否的配置数据集;
6、路由信息初始化后,进入用户定制化的初始页或者首页;
ok,分析得差不多了,下面介绍下具体实操步骤。
npminstalluni-simple-router接下来进行模块化配置,创建文件夹router,文件夹内容如下:
home文件里是所有页面的路由配置,就像这样:
modules文件夹下的index只是一个模块读取的代码;
constfiles=require.context('.',false,/\.js$/)constmodules=[]files.keys().forEach(key=>{if(key==='./index.js')returnconstitem=files(key).defaultmodules.push(...item)})exportdefaultmodulesrouter根级目录下的index内容主要就是路由守卫:
importmodulesfrom'./modules/index.js'importVuefrom'vue'importRouterfrom'uni-simple-router'importstorefrom'@/store/store.js'Vue.use(Router)//初始化constrouter=newRouter({APP:{holdTabbar:false//默认true},h5:{vueRouterDev:true,//完全使用vue-router开发默认false},routes:[...modules]//路由表});//全局路由前置守卫router.beforeEach((to,from,next)=>{//首先判断是否存在路由信息//不存在就先调用接口得到数据//具体内容可以参照上文的方案设计内容})//全局路由后置守卫router.afterEach((to,from)=>{})exportdefaultrouter;最后在app的main.js里需要这么引用:
importrouterfrom'./router/index.js'import{RouterMount}from'uni-simple-router'...//v1.3.5起H5端你应该去除原有的app.$mount();使用路由自带的渲染方式//#ifdefH5RouterMount(app,'#app');//#endif//为了兼容小程序及app端必须这样写才有效果//#ifndefH5app.$mount();//#endif至于后面的路由用法,直接看官方文档,比较清楚,用法跟vue-router差不多。这里要特别说明的是上面代码初始化的那一块的几个配置:holdTabbar:false,vueRouterDev:true,前者表示在app端取代原生的tabbar拦截,在这个插件里拦截;后者表示在h5中完全用vue-router的api,废弃了包括此插件及uniapp的原生api,后者请慎用。
这里其实没什么难度,也不给代码了,很简单。
由于tabbar是单独配置的,原生的uniapp没有动态配置的方法。找了一圈,发现uview的tabbar组件可以实现。这块还是把步骤列一下:一步步来,是可以实现的!
"tabBar":{"list":[{"pagePath":"pages/index/index"},{"pagePath":"pages/about/about"}]},像这样,只留这些内容,跟原生配置比少了许多内容。
这一步可以存在vuex里,因为读取方便,uniapp的数据缓存读取稍微麻烦点。放在vuex里,取的时候很方便,像这样:
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页面可能不是完整的,由用户权限决定。