uni-simple-router
  • 专为uniapp打造的路由器,和uniapp深度集成
  • 通配小程序、App和H5端
  • H5能完全使用vue-router开发
  • 模块化、查询、通配符、路由参数
  • 使 uni-app实现嵌套路由(仅H5端完全使用vue-router)
  • uniapp用到了很多vue的api,但在路由管理的功能相对于vue-router还是比较欠缺的,比如全局导航守卫

官方文档:https://hhyang.cn/v2/start/quickstart.html

一、快速上手
// 针对uniapp HBuilder创建的项目,非cli构建
// NPM 安装
npm install uni-simple-router // 初始化
npm install uni-read-pages // 配合vue.config.js自动读取pages.json作为路由表的方式,源码例如下:扩二 // 配置vue.config.js
const TransformPages = require('uni-read-pages')
const tfPages = new TransformPages()
module.exports = {
configureWebpack: {
plugins: [
new tfPages.webpack.DefinePlugin({
// 配置全局变量
// ROUTES: JSON.stringify(tfPages.routes)
// includes 可自定义,解析pages.json路由配字段的配置, 默认 ['path', 'name', 'aliasPath']
ROUTES: tfPages.webpack.DefinePlugin.runtimeValue(()=>{
const tf = new TransformPages({
includes: ['path', 'name', 'aliasPath']
})
return JSON.stringify(tfPages.routes)
},true)
})
]
}
} // /Applications/HBuilderX.app/Contents/HBuilderX/plugins/uniapp-cli/node_modules/webpack 我的webpack包路径,在软件contents包文件里软件自带的webpack
扩一:webpack插件之DefinePlugin
  • 允许创建一个 在__编译__时可以配置的__全局变量__
  • 场景:区分不同开发模式处理
//  用法:每个传进DefinePlugin的键值都是一个标志或者多个用.连接起来的标识符
new webpack.DefinePlugin({
PRODUCTION: JSON.stringify(true),
BROWSER_SUPPRTS_HTML5: true,
VERSION: JSON.stringify('abcde'),
TWO: '1+1',
'typeof window': JSON.stringify('object')
})
// 使用方式
console.log('Running App version', VERSION)
if(!BROWSER_SUPPRTS_HTML5) require("html5shiv") // 功能标记 来作为一个flag标识启用和禁用构建中的功能
new webpack.DefinePlugin({
'SHOW_PRESSION': JOSN.string(true)
}) // 服务:可以配置不同环境下的url
new webpack.DefinePlugin({
'DEV_URL': JSON.stringify(url_dev),
'PRO_URL': JSON.stringify(url_pro)
})
扩二:uni-read-pages 如何获取pages.json中的路由
// 依赖的源码 - 通过node的path模块获取pages.json文件中的任何信息 (部分是个人注释)
const path = require('path')
const CONFIG = { includes: ['path', 'aliasPath', 'name'] } // 默认获取路由参数属性
// process.cwd() 返回Node.js进程的当前工作目录
// path.resolve(url1, 'abc') => url1/abc
const rootPath = path.resolve(process.cwd(), 'node_modules'); // 获取根路径 /** 解析绝对路径
* @param {Object} dir
*/
function resolvePath(dir) {
return path.resolve(rootPath, dir);
}
// 类
class TransformPages {
constructor(config) {
// 组合 自定义获取配置属性
config = { ...CONFIG, ...config };
this.CONFIG = config; // ↓本机文件路径(HBuilderX包文件里自带的webpack模块路径) /Applications/HBuilderX.app/Contents/HBuilderX/plugins/uniapp-cli/node_modules/webpack
this.webpack = require(resolvePath('webpack'));
this.uniPagesJSON = require(resolvePath('@dcloudio/uni-cli-shared/lib/pages.js')); // TODO: 根据CONFIG解析pages.json中的路由信息 和 小程序 分包下的路由
this.routes = this.getPagesRoutes().concat(this.getNotMpRoutes()); }
// 获取所有pages.json下的内容 返回json
get pagesJson() {
return this.uniPagesJSON.getPagesJson();
} // 通过读取pages.json文件 生成直接可用的routes
getPagesRoutes(pages = this.pagesJson.pages, rootPath = null) {
const routes = [];
for (let i = 0; i < pages.length; i++) {
const item = pages[i];
const route = {};
for (let j = 0; j < this.CONFIG.includes.length; j++) {
const key = this.CONFIG.includes[j];
let value = item[key];
if (key === 'path') {
value = rootPath ? `/${rootPath}/${value}` : `/${value}`
}
if (key === 'aliasPath' && i == 0 && rootPath == null) {
route[key] = route[key] || '/'
} else if (value !== undefined) {
route[key] = value;
}
}
routes.push(route);
}
return routes;
} // 解析小程序分包路径
getNotMpRoutes() {
const { subPackages } = this.pagesJson;
let routes = [];
if (subPackages == null || subPackages.length == 0) {
return [];
}
for (let i = 0; i < subPackages.length; i++) {
const subPages = subPackages[i].pages;
const root = subPackages[i].root;
const subRoutes = this.getPagesRoutes(subPages, root);
routes = routes.concat(subRoutes)
}
return routes
}
/**
* 单条page对象解析
* @param {Object} pageCallback
* @param {Object} subPageCallback
*/
parsePages(pageCallback, subPageCallback) {
this.uniPagesJSON.parsePages(this.pagesJson, pageCallback, subPageCallback)
}
}
module.exports = TransformPages
二、H5模式
2.1 路由配置
import {RouterMount,createRouter} from 'uni-simple-router';
const router = createRouter({
// 路由配置
routes: [
{
path: '/pages/index/index', // 必须和pages.json中相同
extra: {
pageStyle: { color: '#f00' }// 及其它自定义参数
}
}
]
})
// 组件中可以通过 this.$Route 查看路由元信息
2.2 完全使用vue-router开发 (H5端)
  • 嵌套路由时,若使用name方式跳转,仅支持 this.$router.push({ name:  children1 })
// 使用 vue-router开发将会失去uniapp的生命周期
const router = createRouter({
h5: {
vueRouterDev: true, // 完全使用vue-router开发 默认是false
},
// 路由配置
routes: [
{
path: '/',
name: 'home',
component: () => import('@/common/router/home.vue'),
// 嵌套路由(仅H5端),小程序端会重新页面打开
children: [
{
path: 'home/children1',
name: 'children1',
component: () => import('@/common/router/children1.vue')
},
{
path: 'home/children2',
name: 'children2',
component: () => import('@/common/router/children2.vue')
}
]
}
]
})
2.3 H5 路由传参
// 除vue-router外,美化url可以在基础配置时,定义aliasPath变量,设置路由别名(浏览器地址栏展示名称)
// 别名的设置,如果设置了别名,通过push路径的方式,必须使用aliasPath的路径才能生效
const router = createRouter({
routes:[{
name:'router1',
//为了兼容其他端,此时的path不能少,必须和 pages.json中的页面路径匹配
path: "/pages/tabbar/tabbar-1/tabbar-1",
aliasPath: '/tabbar-1',
},]
}); // uni-simple-router路由跳转
// aliasPath命名的路由 => name传递参数需 params
this.$Router.push({ name: 'detail', params: { id: 1 } })
// 带查询参数,变成 /home/id=1 => path 对应query,params失效
this.$Router.push({ path: '/pages/index/detail', query: { id: 1 }})
2.4 H5端路由捕获所有路由或404路由
path:'*' // 通常用于客户端404错误,如果是history模式,需要正确配置服务器
path: '/detail-*'
// 路由的优先级根据 定义的先后
2.5 路由懒加载
  • 打包构建应用时,Javascript包会变得非常大,影响页面加载,把不同路由对应的组件分割成不同的代码块,然后当路由被访问的时候才加载对应组件。

  •   const Foo = () => import('./Foo.vue')
    // 把组件按组分块 使用 命名 chunk
    const Foo = () => import(/*webpackChunkName:"group-foo"*/ './Foo.vue')
    const Bar = () => import(/*webpackChunkName:"group-foo"*/ './Bar.vue')
三、小程序模式
  • 注:小程序系列无法拦截原生tabbar及原生导航返回,如需拦截使用自定义tabbar、header

  • 通过api进行切换时,像uni.switchTab()和this.$Router.pushTab()方法会触发拦截的;仅底部原生tabbar进行切换时不触发拦截

  • 强制触发守卫:forceGuardEach(replaceAll, false) 每次调用api都会重新按流程触发已经声明的所有守卫

    • 小程序端默认:插件api跳转、uni导航api跳转和首屏加载
    • 使用路由守卫:通过点击事件强制触发、混入到onshow回调触发
  • 跳转路由锁:animationDuration保留给redirection\push足够时间,等切换完成页面后才放行下次跳转

    const router = createRouter({
    platform: process.env.VUE_APP_PLATFORM,
    // ① 路由锁
    applet: {
    animationDuration: 300 // 默认300ms
    // animationDuration: 0 // 不精准 只捕捉跳转api下的complete函数
    },
    // ②优雅解锁 error.type: 0 表示 next(false)、1表示next(unknownType)、2表示加锁状态,禁止跳转、3表示在获取页面栈时,页面栈不够level获取
    routerErrorEach:(error, router) => {
    if (error.type === 3) {
    router.$lockStatus = false
    }
    },
    routes: [...ROUTES]
    })
四、路由跳转
4.1 组件跳转
  • vue-router中可以通过router-link组件进行页面跳转,uni-simple-router也提供了类似的组件,需要手动注册

  •   // main.js
    import Link from './node_modules/uni-simple-router/dist/link.vue'
    Vue.component('Link', Link)
  •   // 通过path直接跳转 并指定跳转类型
    <Link to="/tabbar1" navType="pushTab">
    <button type="primary">使用path对象跳转</button>
    </Link>
4.2 编程式导航
  • 通过this.$Router获取路由对象;push、pushTab、replace、back等api进行路由跳转
  • 注:path搭配query参数、name搭配params参数
  • 导航使用方式同vue-router
五、跨平台模式
5.1 提前享用生命周期
  • uniapp由于只用onLoad接受options参数、onShow不接受;传递深度对象参数时,需要先编码再传递解码

  •   // 动态改变参数 使 onLoad和onShow支持options
    const router = createRouter({
    platform: process.env.VUE_APP_PLATFORM,
    routes: [...ROUTES],
    beforeProxyHooks: {
    onLoad(options, next){
    next([router.currentRoute.query]);
    },
    onShow([options], next){
    console.log(this);
    const args=options||router.currentRoute.query;
    next([args]);
    },
    },
    });
5.2 导航守卫
  • 全局前置守卫

    /**
    * to: Route 即将进入的目标
    * from: Route 当前导航正要离开的路由
    * next: Function 该方法的resolve钩子函数必须调用,执行效果依赖next方法的调用参数
    * -- next()调用参数:管道中的下个钩子; next(false)中断当前导航;
    * -- next('/')/({path: '/'})跳转到一个不同的地址。当前的导航被中断,然后进行一个新的导航
    * -- next({delta: 2, NAVTYPE: 'back'}) 中断当前导航,调用新的跳转类型,同时返回两层页面
    **/
    router.beforeEach((to, from, next) => {
    // ...
    // next()
    // NAVTYPE定义跳转方式,两者相同非必填
    if (to.name == 'tabbar-5') {
    next({
    name: 'router4',
    params: {
    msg: '我拦截了tab5并重定向到了路由4页面上',
    },
    NAVTYPE: 'push'
    });
    } else{
    next();
    }
    })
  • 全局后置守卫

    // 不接受next函数也不改变导航本身
    router.afterEach((to,from) => {})
  • 路由独享守卫

    // 路由配置上直接定义beforeEnter守卫
    const router = createRouter({
    routes: [{
    path: '/pages/home/index',
    beforeEnter:(to,from,next) => {
    // 参数同上全局前置守卫
    next()
    }
    }]
    })
  • 组件内的守卫

    // 组件内配置beforeRouteLeave守卫 - 直接调用beforeRouteLeave方法
    export default {
    beforeRouteLeave(to, from, next) {
    // 导航离开该组件的对应路由时调用
    // 可以访问组件实例this
    next()
    }
    }
六、路由守卫-模块化
//  创建 router文件夹,模块化配置 文件结构
|+------------------------+|
| router |
| |+--------------------+| |
| | modules | |
| | |+----------------+| | |
| | | home.js | | |
| | | index.js | | |
| | |+----------------+| | |
| |+--------------------+| |
| index.js |
|+------------------------+|
// home.js
const home = [
{
path: '/pages/home/index',
name: 'home'
}
]
export default home
// modules下的index.js是一个模块读取
// ① require.context(directory, useSubdirectories, regExp) 具体详情:如下扩三
const files = require.contxt('.',false,/.js$/)
const modules = [] files.keys().froEach(key => {
if (key === './index.js') return
const item = files(key).default
modules.push(...item)
}) export default modules // 将所有模块的路由模块整合到一起, routes Array
// router下的index.js 路由守卫
import modules from './modules/index.js'
import Vue from 'vue'
import CreateRouter from 'uni-simple-router'
import store from '@/store/store.js' Vue.use(CreateRouter)
//初始化
const router = new CreateRouter({
APP: {
holdTabbar: false //默认true
},
h5: {
vueRouterDev: true, //完全使用vue-router开发 默认 false
},
// 也可以 通过uni-read-pages来读取pages.json文件的路由表,配合vue.config.js
// router: [...ROUTES] // ROUTES是通过webpack的defaultPlugin编译成全局变量,具体操作上文
routes: [...modules] //路由表
}); //全局路由前置守卫
router.beforeEach((to, from, next) => {
// 首先判断是否存在路由信息
//不存在就先调用接口得到数据
})
// 全局路由后置守卫
router.afterEach((to, from) => {})
export default router;
扩三、require.context用法
// require.context(directory, useSubdirectories, regExp)
// directory: 表示检索的目录
// useSubdirectories: 表示是否检索子文件夹
// regExp: 匹配文件的正则表达式
// 返回值: resolve是一个函数,返回已解析请求的模块ID; keys是一个函数,它返回上下文模块可以处理的所有可能请求的数组;
// 使用场景:①用来组件内引入多个组件;②在main.js内引入大量公共组件;
// ①组件内引入多个组件 - webpack
const path = require('path')
const files = require.context('@/components/home', false, /\.vue$/) //值类型 ['./home.js', 'detail.js',...]
const modules = {} files.keys().forEach(key => {
const name = paths.basename(key, '.vue') // 去掉文件名的 .vue后缀
modules[name] = files(key).default || files(key)
})
// modules { home: '{module样式路径}', detail: '{}', ... }
export default {
...,
data() { return {}},
components: modules
}
// ②在main.js内引入大量公共组件
import Vue from 'vue'
// 引入自定义组件
const requireComponents = require.context('../views/components',true,'/\.vue/')
// 遍历出每个数组的路径
requireComponents.keys().forEach(fileName => {
const reqCom = requireComponents(fileName)
// 获取组件名
const reqComName = reqCom.name || fileName.replace(/\.\/(.*)\.vue/, '$1')
// 组件挂载
Vue.components(reqComName, reqCom.default || reqCom)
})

uni-simple-router的更多相关文章

  1. 【p4tutorials】P4 v1.1 Simple Router

    fork了p4tutorials,想从里面窥探一些门道. 本文相关的原文链接:ReadMe 说明: 下面的这个P4程序,是当下最著名的 simple_router 程序的一个版本,是根据P4的1.1版 ...

  2. GO语言的开源库

    Indexes and search engines These sites provide indexes and search engines for Go packages: godoc.org ...

  3. Node.js Web 开发框架大全《路由篇》

    这篇文章与大家分享优秀的 Node.js 路由(Routers)模块.Node 是一个服务器端 JavaScript 解释器,它将改变服务器应该如何工作的概念.它的目标是帮助程序员构建高度可伸缩的应用 ...

  4. 从WeUI学习到的知识点

    WeUI是微信Web服务开发的UI套件, 目前包含12个模块 (Button, Cell, Toast, Dialog, Progress, Msg, Article, ActionSheet, Ic ...

  5. WeUI

    从WeUI学习到的知识点   WeUI是微信Web服务开发的UI套件, 目前包含12个模块 (Button, Cell, Toast, Dialog, Progress, Msg, Article, ...

  6. Go语言(golang)开源项目大全

    转http://www.open-open.com/lib/view/open1396063913278.html内容目录Astronomy构建工具缓存云计算命令行选项解析器命令行工具压缩配置文件解析 ...

  7. php前端控制器2

    Front Controllers act like centralized agents in an application whose primary area of concern is to ...

  8. [转]Go语言(golang)开源项目大全

    内容目录 Astronomy 构建工具 缓存 云计算 命令行选项解析器 命令行工具 压缩 配置文件解析器 控制台用户界面 加密 数据处理 数据结构 数据库和存储 开发工具 分布式/网格计算 文档 编辑 ...

  9. php框架Yaf路由重写

    php框架Yaf路由重写 通常为了友好的URL格式,会进行站点URL的重写,可以在webserver(Nginx)的配置中进行rewrite,也可在在程序端进行 以下使用Yaf框架进行URL的重写,进 ...

  10. Source Routing

    Source routing Followed by book_Principles and Practices of Interconnection Networks, p204. With sou ...

随机推荐

  1. CSS - 定位属性position使用详解(static、relative、fixed、absolute)

    position 属性介绍 (1)position 属性自 CSS2 起就有了,该属性规定元素的定位类型.所有主流浏览器都支持 position 属性. (2)position 的可选值有四个:sta ...

  2. 【uniapp 开发】如何给边框添加阴影效果

    css的box-shadow是用来添加边框阴影效果的. 属性值详解: 1.inset 可选值,默认阴影在盒子外 使用inset后,阴影在盒子内,即使指定边框或者透明边框,阴影依然存在. 2. 这是头两 ...

  3. LINUX执行shutdown.sh提示:-bash: ./startup.sh: Permission denied

    在执行./startup.sh,或者./shutdown.sh的时候,爆出了Permission denied, 其实很简单,就是今天在执行tomcat的时候,用户没有权限,而导致无法执行, 用命令c ...

  4. sequelize模型

    model表示数据库中的表,有时它也会被称为"模型"或"工厂".Model不能通过构造函数创建,只能通过sequlize.define方法来定义或通过sequl ...

  5. 圆桌killer

    [问题描述] 圆桌上围坐着2n个人.其中n个人是好人,另外n个人是坏人.如果从第m(m<=2n)个人开始数数,数到第k个人,则立即处死该人:然后从被处死的人之后重新开始数数,再将数到的第k个人处 ...

  6. 关于javaweb学习终点的一些感悟

    学习完javaweb后,自己做了一套管理项目,使用了mybatis,themeleaf和servlet.大致明白了servlet的真实应用场景. 说白了servlet就是用来指定浏览器url后面输入了 ...

  7. Go xmas2020 学习笔记 07、Formatted & File I/O

    07-Formatted & File I/O. I/O steams. formatted I/O. fmt functions. file I/O. Practice ① I/O. Alw ...

  8. Golang 泛型的简单使用

    go 学习泛型,利用泛型编写对数据集合执行操作的方法.

  9. HTTP:聊一聊HTTP中的强制缓存

    http响应response headers中会有一个cache-control,这个参数就是用来做强制缓存的 一.什么是强制缓存 强制缓存就是服务端告诉客户端某些资源(JS CSS IMG)需要按照 ...

  10. A标签上使用onclick事件,js函数响应成功,单会刷新当前页面陷阱

    BEGIN; 最近在做html页面时,有时候会遇到以前没遇到的各种奇葩问题. 目前要记载的,就是其中之一. 我们在写链接的时候,即A标签,最普通的写法无非是 <a href='http://ww ...