不如摸鱼去
不如摸鱼去
  • 发布:2023-06-01 10:18
  • 更新:2023-07-31 17:57
  • 阅读:2389

基于vue3的uni-app路由库uni-mini-router助你实现跳转、传参、拦截等路由功能

分类:uni-app

介绍

uni-mini-router是一个基于vue3uni-app框架的轻量级路由库,它提供了类似Vue Router的API和功能,可以帮助开发者实现在uni-app中进行路由跳转、传参、拦截等常用操作。

uni-mini-router支持多种跳转方式,包括普通跳转、重定向、切换TabBar页面等。它也提供了一些高级特性,如路由拦截、编程式导航等。

总之,如果你在uni-app开发过程中需要使用到路由功能,可以考虑使用uni-mini-router来简化你的开发工作。

安装uni-mini-router

Yarn
yarn add uni-mini-router -D
npm
npm install uni-mini-router --save

生成路由表

我们提供了两种方式来生成路由表:uni-parse-pagesuni-read-pages-vite,这两种方式都可以实现将pages.json中的路由信息转化为uni-mini-router需要的路由表信息,其中uni-read-pages-vite依赖vite,在编译时将读取pages.json生成的路由表注入全局变量,而uni-parse-pages不依赖vite,在应用每次热重载时都会从pages.json中读取信息生成路由表。

由于uni-app在编译到小程序端时无法触发vite的热更新,所以目前只有使用uni-parse-pages生成路由表才可以实现路由信息热更新的功能。

注意!!!uni-parse-pagesuni-mini-router@0.1.0版本起获得支持,在之前的版本使用会有问题。

以下两种方式二选一:

使用uni-parse-pages生成路由表(0.1.0起支持)

安装

Yarn
yarn add uni-parse-pages -D
npm
npm install uni-parse-pages --save

使用uni-read-pages-vite生成路由表

安装

Yarn
yarn add uni-read-pages-vite
npm
npm install uni-read-pages-vite

配置

配置uni-read-pages-vite

配置 vite.config.ts 通过 define 注入全局变量 查看文档

注意:在 Vite 中使用 define 注入的全局变量并不是热更新的,因为这些变量是在构建时被注入到代码中的,而不是在运行时动态生成的。这意味着如果您更新了page.json,则需要重新构建应用程序才能使更改生效。

配置vite.config.ts
CLI创建的项目配置
//vite.config.ts  
import { defineConfig } from "vite";  
import uni from "@dcloudio/vite-plugin-uni";  
import TransformPages from 'uni-read-pages-vite'  
  
export default defineConfig({  
  plugins: [uni()],  
  define: {  
    ROUTES: new TransformPages().routes, // 注入路由表  
  }  
});
HbuilderX创建的项目配置
//vite.config.ts  
import { defineConfig } from "vite";  
import uni from "@dcloudio/vite-plugin-uni";  
import TransformPages from 'uni-read-pages-vite'  
  
export default defineConfig({  
  plugins: [uni()],  
  define: {  
    ROUTES: new TransformPages(__dirname).routes, // 注入路由表  
  }  
});
声明文件type.d.ts

.d.ts文件的作用是描述JavaScript库、模块或其他代码的类型声明和元数据,以便编辑器和开发者能够更好地理解和使用该代码。在编译时,TypeScript编译器会使用.d.ts文件来验证代码正确性,并帮助开发者在开发过程中提供更好的代码提示和自动补全功能。

在项目src目录下(HbuilderX创建的项目可以在根目录下)创建type.d.ts文件。

//type.d.ts  
declare const ROUTES: []

配置uni-mini-router

项目src目录下(HbuilderX创建的项目可以在根目录下)创建router文件夹,并在该文件夹创建index.ts

配置router/index.ts

根据生成路由表方式的不同,我们这里也提供了两种配置router的方式,也是二选一

uni-parse-pages

import { createRouter } from 'uni-mini-router'  
// 导入pages.json  
import pagesJson from '../pages.json'  
// 引入uni-parse-pages  
import pagesJsonToRoutes from 'uni-parse-pages'  
// 生成路由表  
const routes = pagesJsonToRoutes(pagesJson)  
const router = createRouter({  
  routes: [...routes] // 路由表信息  
})  
export default router

uni-read-pages-vite

此处的ROUTES就是配置vite.config.ts步骤中注入的

import { createRouter } from 'uni-mini-router'  
const router = createRouter({  
  routes: [...ROUTES] // 路由表信息  
})  
export default router

配置main.ts

import { createSSRApp } from 'vue'  
import App from './App.vue'  
import router from './router'  
export function createApp() {  
  const app = createSSRApp(App)  
  app.use(router)  
  return {  
    app  
  }  
}

配置pages.json

在pages.json中为页面路由指定name字段后,即可以使用name跳转

注意:此处定义的name字段必须全局唯一。

//  pages.json  
{  
  "pages": [{  
      "path": "pages/home/Home",  
      "name": "home", // 路由 name 用于命名路由的跳转  
      "style": {  
        "mp-alipay": {  
          "allowsBounceVertical": "NO"  
        },  
        "navigationBarTitleText": "首页"  
      }  
    },  
    {  
      "path": "pages/login/Login",  
      "name": "login",  
      "style": {  
        "mp-alipay": {  
          "allowsBounceVertical": "NO"  
        },  
        "navigationBarTitleText": ""  
      }  
    },  
    {  
      "path": "pages/mine/Mine",  
      "name": "mine",  
      "style": {  
        "navigationBarTitleText": "",  
        "navigationBarBackgroundColor": "#E7F0FF"  
      }  
    }  
  ],  
  "tabBar": {  
    "color": "#bfbfbf",  
    "selectedColor": "#0165FF",  
    "backgroundColor": "#ffffff",  
    "list": [{  
        "pagePath": "pages/home/Home",  
        "iconPath": "static/icon_home.png",  
        "selectedIconPath": "static/icon_home_selected.png",  
        "text": "首页"  
      },  
      {  
        "pagePath": "pages/mine/Mine",  
        "iconPath": "static/icon_mine.png",  
        "selectedIconPath": "static/icon_mine_selected.png",  
        "text": "我的"  
      }  
    ]  
  },  
  "globalStyle": {  
    "navigationBarTextStyle": "black",  
    "navigationBarBackgroundColor": "#FFF",  
    "backgroundColor": "#F8F8F8"  
  }  
}

配置自动按需导入(可选)

unplugin-auto-import:是一个为 ViteWebpackRollupesbuild 按需自动导入 API,支持 TypeScript的插件,我们基于此插件实现自动按需导入。

不使用按需导入,则需要手动import

import { useRouter } from 'uni-mini-router'  
const router = useRouter()  
router.push('/')

使用按需导入后

const router = useRouter()  
router.push('/')

安装unplugin-auto-import

yarn add uni-mini-router -D

配置unplugin-auto-import

详细配置方案见unplugin-auto-import,这里给出支持uni-mini-router的简易配置

//vite.config.ts  
import { defineConfig } from 'vite'  
import TransformPages from 'uni-read-pages-vite'  
import uni from '@dcloudio/vite-plugin-uni'  
import AutoImport from 'unplugin-auto-import/vite'  
export default defineConfig({  
  base: './',  
  plugins: [  
    uni(),  
    AutoImport({  
      imports: [  
        'vue',  
        'uni-app',  
        'pinia',  
        {  
          from: 'uni-mini-router',  
          imports: ['createRouter', 'useRouter', 'useRoute']  
        }  
      ],  
      dts: 'src/auto-imports.d.ts', // 这里src目录必须是已存在的,如果是HbuilderX创建的项目是没有src目录的,可以配置为 dts: 'auto-imports.d.ts'  
      eslintrc: {  
        enabled: true,  
        globalsPropValue: true  
      }  
    })  
  ],  
  define: {  
    ROUTES: new TransformPages().routes  
  }  
})

总结

unplugin-auto-import 可以帮助我们实现按需自动导入第三方库的API,提升开发效率,但是它也同样存在一些缺点,例如:

  • 可能会影响代码可读性:自动导入模块可能会导致代码可读性降低,因为开发者可能不知道哪些模块被自动导入了。

  • 可能会导致性能问题:自动导入模块可能会导致性能问题,因为它需要扫描整个代码库来查找缺失的模块。

所以在提升开发效率的同时也要兼顾可读性和性能问题,尽量将一些被广泛认知和使用、不用关注实现、不变的内容作为自动按需引入的对象,而项目内的代码如果自动按需引入是否会增加开发人员的心智负担,则需要我们做出相应的权衡。

使用

编程式导航

注意:这里nameparams搭配使用,而path 可以与 query 一起使用。

基础用法

<script setup lang="ts">  
import { ref } from 'vue'  
import { useRouter } from 'uni-mini-router'  
import { getCurrentInstance } from 'vue'  
  
// 使用hooks(推荐)  
let router = useRouter()  
  
// 或者 使用全局挂载的router  
router = instence?.appContext.config.globalProperties.$Router  
  
// 字符串路径  
router.push('/user')  
  
// 带有路径的对象  
router.push({ path: '/user' })  
  
// 命名的路由,并加上参数,让路由建立 url  
router.push({ name: 'user', params: { username: 'eduardo' } })  
  
// 带查询参数,结果是 /user?username=eduardo  
router.push({ path: '/user', query: { username: 'eduardo' } })  
  
</script>

在user.vue接收传入的对象参数

<script setup lang="ts">  
onLoad((option) => {  
  if (option && option.username) {  
    const username = option.username  
  }  
})  
</script>

传递对象参数

url有长度限制,太长的字符串会传递失败,可改用窗体通信全局变量,另外参数中出现空格等特殊字符时需要对参数进行编码,如下为使用encodeURIComponent对参数进行编码的示例。

<script setup lang="ts">  
import { ref } from 'vue'  
import { useRouter } from 'uni-mini-router'  
import { getCurrentInstance } from 'vue'  
  
let router = useRouter()  
  
const user = {  
  name:'小星星',  
  label:"小熊熊"  
}  
  
// 命名的路由,传递对象参数  
router.push({ name: 'user', params: { user: encodeURIComponent(JSON.stringify(user)) } })  
  
// path+query,传递对象参数  
router.push({ path: '/user', query: { user: encodeURIComponent(JSON.stringify(user)) } })  
  
</script>

在user.vue接收传入的对象参数

<script setup lang="ts">  
onLoad((option) => {  
  if (option && option.user) {  
    const user = JSON.parse(decodeURIComponent(option.user))  
  }  
})  
  
// 返回  
function back() {  
  router.back()  
}  
</script>

导航守卫

uni-mini-router支持全局前置导航守卫 beforeEach全局后置导航守卫 afterEach,主要用来通过跳转或取消的方式守卫导航。

全局前置守卫 beforeEach

你可以使用 router.beforeEach 注册一个全局前置守卫:

const router = createRouter({ ... })  
  
router.beforeEach((to, from, next) => {  
  // next入参 false 以取消导航  
  next(false)  
})
beforeEach守卫方法接收三个参数:
  • to: 即将要进入的目标
  • from: 当前导航正要离开的路由
  • next: 用于reslove beforeEach钩子,需要确保 next 在导航守卫中都被严格调用一次-
    • next(): 执行默认路由跳转逻辑
    • next(false): 终止跳转逻辑
    • next({ path: '/' }): 跳转到不同的页面
    • next({ path: '/', navType: 'replaceAll' }): 改变当前跳转类型并跳转到不同的页面,可以通过navType指定新的跳转类型。(实例为中断当前导航,改用replaceAll方法跳转到新的页面)

全局后置钩子 afterEach

你也可以注册全局后置钩子,然而和守卫不同的是,这些钩子不会接受 next 函数也不会改变导航本身

const router = createRouter({ ... })  
  
router.afterEach((to, from) => {  
  console.log(to)  
  console.log(from)  
})

它对于分析、更改页面标题、声明页面等辅助功能以及许多其他事情都很有用。

API 文档

createRouter

▸ createRouter(options): Router

创建一个可以被 Vue 应用使用的 Router 实例。

参数

| 名称 | 类型 | 描述 |
| ------- | --------------- | --------------- |
| options | RouterOptions | RouterOptions |

返回值

Router

useRouter

▸ useRouter(): Router

返回路由器实例。相当于在模板中使用 $Router。

不可以脱离 Vue 上下文使用

返回值

Router

useRoute

▸ useRoute(): Route

返回当前的路由地址信息。相当于在模板中使用 $Route。

不可以脱离 Vue 上下文使用,且只能在页面mount之后才可与使用。当使用场景为外部链接跳转进入或H5页面刷新时,默认从当前链接中取得query参数并放在Routequery字段中,这种场景建议走onLoad声明周期获取参数。

返回值

Route

Router实例方法

push方法

▸ router.push(target:RouteLocationRaw): void

保留当前页面,跳转到应用内的某个页面,相当于使用 uni.navigateTo(OBJECT)

pushTab方法

▸ router.pushTab(target:RouteLocationRaw): void

跳转到 tabBar 页面,并关闭其他所有非 tabBar 页面,相当于使用 uni.switchTab(OBJECT)

replace方法

▸ router.replace(target:RouteLocationRaw): void

关闭当前页面,跳转到应用内的某个页面,相当于使用 uni.redirectTo(OBJECT)

replaceAll方法

▸ router.replaceAll(target:RouteLocationRaw): void

关闭所有页面,打开到应用内的某个页面,相当于使用 uni.reLaunch(OBJECT)

back方法

▸ router.back(level?: number): void

关闭当前页面,返回上一页面或多级页面,相当于使用 uni.navigateBack(OBJECT)

演示项目:Vue3-Uni-TS-Template基础模板

使用文档:地址

插件市场地址:uni-mini-router

0 关注 分享

要回复文章请先登录注册

wangMr

wangMr

回复 hhyang :
大佬,你好,那当我没有跳转的时候,使用router.back()方法,就会报错,有没有什么处理方法呢?就是区分他是否有可返回的页面栈,如果没有,直接终止,不让他执行 router.back()方法
2023-07-31 17:57
wangMr

wangMr

回复 不如摸鱼去 :
大佬,你好,那当我没有跳转的时候,使用router.back()方法,就会报错,有没有什么处理方法呢?就是区分他是否有可返回的页面栈,如果没有,直接终止,不让他执行 router.back()方法
2023-07-31 17:57
不如摸鱼去

不如摸鱼去 (作者)

回复 hhyang :
不错
2023-07-12 15:22
hhyang

hhyang

如果你正在使用 vue3 + vite 请参考 [uni-simple-router v3 路由、拦截、最优雅的解决方案重磅来袭](https://ask.dcloud.net.cn/article/40621),或者查看 [官方文档](https://v3.hhyang.cn/)
2023-07-12 11:34
不如摸鱼去

不如摸鱼去 (作者)

插件市场地址:[uni-mini-router](https://ext.dcloud.net.cn/plugin?id=11208)
2023-06-01 14:51