uni-app提供了路由功能来实现页面跳转,但是在使用的过程中我们还是发现有些不方便的地方,如下图:

页面的跳转存在哪些问题呢

  1. 页面路径不好的管理问题

    1. 为什么不好管理:就是改页面路径,或者说分包的时候不用一个个找着改
  2. 传递参数的方式不太友好
    1. 为什么不友好:需要手动拼接参数列表
  3. 参数类型单一,只支持string
    1. 不管传string还是number和boolean得到的都是字符串
  4. 传特殊字符时会发现参数被截断(比如传二维码信息)
    1. 原因是不能包括(=&?)等特殊字符

首先先做一下准备工作

创建一个项目

第一个问题好解决,先做一个集中管理,创建一个文件(router.js)来集中管理,目录结构下

代码如下

export default {// 首页页面index: '/pages/index/index.vue',// 我的页面my: '/pages/my/index.vue'
}复制代码

使用的时候变成这样

<template><view class="content"><image class="logo" src="/static/logo.png"></image><view><text class="title">{{title}}</text></view><button @click="openPage">跳转到我的页面</button></view>
</template>
<script>import url from '../../router'export default {data() {return {title: 'index'}},onLoad() {    },methods: {openPage () {uni.navigateTo({url: url.my})}}}
</script>复制代码

使用的时候需要引入router.js特别麻烦,先不解决这个问题

下面来看第二和第三个问题

先看个例子

参数比较多的情况下这样确实不好操作麻烦,能不能把参数部分单独拿出来然后拼接到url上面呢?

惊奇的发现传过来的数字竟然变成字符串了,参数不能保真

第四个问题就不演示了

废话不多说了,说了这么多,相信你们也应该知道问题的所在了,下面就来解决这些问题 (渐进式讲解

首先创建一个文件(MinRouter.js)目录结构如下

下面代码解决了第一个问题

不再需要使用是引入router.js文件

import urlSet from './router';
function openPage (url) {  uni.navigateTo({url: `${urlSet[url]}`})
}
export default openPage复制代码

main.js文件做如下修改

import Vue from 'vue'
import App from './App'
// 引入MinRouter文件
import openPage from './MinRouter'
Vue.config.productionTip = false
App.mpType = 'app'
// 添加到全局
global.openPage = openPage
const app = new Vue({...App
})
app.$mount()复制代码

使用方式

<template><view class="content"><image class="logo" src="/static/logo.png"></image><view><text class="title">{{title}}</text></view><button @click="toPage">跳转到我的页面</button>
</view>
</template>
<script> export default {data() {      return {title: 'index'}},onLoad() {    },methods: {toPage () {global.openPage('my')}    }
}
</script>复制代码

下面来解决第二和第三个问题

第三个问题想必很多人都遇到过,本来就想传递一个number,结果不管传什么都会变成string。

有什么办法可以让数据变成字符串之后,还能还原成原来的类型?

使用JSON就能解决上面的问题了,而且也很好的解决了第二个问题

试着修改原来的代码

import urlSet from './router';
function openPage (url, query) {const queryStr = JSON.stringify(query)uni.navigateTo({url: `${urlSet[url]}?query=${queryStr}`})}
export default openPage复制代码

使用方式

<template><view class="content"><image class="logo" src="/static/logo.png"></image><view><text class="title">{{title}}</text></view><button @click="toPage">跳转到我的页面</button></view></template><script>
export default {data() {return {title: 'index'}},onLoad() {    },methods: {toPage () {global.openPage('my', {id: 123})}}}
</script>复制代码

下面来解决第四个问题

(=&?)等特殊字符在url上面是有特殊含义的,所以我们要把json字符串encode一下

import urlSet from './router';
function openPage (url, query) {const queryStr = encodeURIComponent(JSON.stringify(query))uni.navigateTo({url: `${urlSet[url]}?query=${queryStr}`})}
export default openPage复制代码

到此上面的问题全部解决了,但是感觉还是不太好,能不能封装成Vue插件,类似VueRouter

答案是肯定的

封装成型MinRouter

router.js文件改成如下

import MinRouter from './MinRouter'
// 配置路由
const router = new MinRouter({routes: [{// 页面路径path: 'pages/index/index',name: 'index'},{path: 'pages/my/index',name: 'my'}]})
export default router复制代码

main.js文件改成如下

import Vue from 'vue'
import App from './App'
// 引入MinRouter文件
import MinRouter from './MinRouter'
// 引入router文件
import minRouter from './router'
Vue.config.productionTip = false
// 注册插件
Vue.use(MinRouter)
App.mpType = 'app'
const app = new Vue({...App,minRouter
})
app.$mount()复制代码

上面的代码配置中已经很像VueRouter了

在MinRouter文件添加以下代码

const toString = Object.prototype.toStringfunctionisObject (value) {return toString.call(value) === '[object Object]'
}
function isString (value) {return toString.call(value) === '[object String]
'}
function isDefault (value) {return value === void 0
}
function install (Vue) {Vue.mixin({beforeCreate: function () {if (!isDefault(this.$options.minRouter)) {Vue._minRouter = this.$options.minRouter}
}
})
Object.defineProperty(Vue.prototype, '$minRouter', {get: function () {return Vue._minRouter._router}})
}
function MinRouter (options) {if (!(this instanceof MinRouter)) {throw Error("MinRouter是一个构造函数,应该用`new`关键字调用")}isDefault(options) && (options = {})this.options = optionsthis._router = options.routes || []
}
MinRouter.install = install
export default MinRouter复制代码

下面来设定openPage的参数

name:表示要跳转的页面

query:跳转页面所带的参数

调用方式:   openPage({name: 跳转的页面, query: {id: 123}})复制代码

openPage函数如下

function openPage (args) {let {name, query = {}} = argslet queryStr = null, pathqueryStr = encodeURIComponent(JSON.stringify(query))this.$minRouter.forEach(item => {if (item.name === name) {path = item.path}})return new Promise((resolve, reject) => {uni.navigateTo({url: `/${path}?query=${queryStr}`,success: resolve,fail: reject})})
}复制代码
this.$minRouter已经在上面的代码代理过来了,不要觉得奇怪,其实就是配置路由中的routes复制代码

上面的只能的路由只能使用这种方式navigateBack

这样肯定是不行的,你们可能会想在加一个参数去控制路由跳转方式,但是这样觉得不是很简便,既然openPage函数不能加,能不能在路由里面加了?

下面来修改router.js文件

import MinRouter from './MinRouter'
// 配置路由
const router = new MinRouter({routes: [{// 页面路径path: 'pages/index/index',// type必须是以下的值['navigateTo', 'switchTab', 'reLaunch', 'redirectTo']// 跳转方式(默认跳转方式)type: 'navigateTo',name: 'index'},{path: 'pages/my/index',name: 'my'}]})
export default router复制代码

openPage函数如下

function openPage (args) {let name, query = {}, queryStr = null, path, typeswitch (true) {case isObject(args):({name, query = {}} = args)breakcase isString(args):name = argsbreakdefault:throw new Error('参数必须是对象或者字符串')}if (isObject(query)) {queryStr = encodeURIComponent(JSON.stringify(query))} else {throw new Error('query数据必须是Object')}this.$minRouter.forEach(item => {if (item.name === name) {path = item.pathtype = item.type || 'navigateTo'}})if (!['navigateTo', 'switchTab', 'reLaunch', 'redirectTo'].includes(type)) {throw new Error(`name:${name}里面的type必须是以下的值['navigateTo', 'switchTab', 'reLaunch', 'redirectTo']`)}return new Promise((resolve, reject) => {uni[type]({url: `/${path}?query=${queryStr}`,success: resolve,fail: reject})})
}复制代码

说了这么多还没说怎么解析路由参数了

下面函数是解析路由参数的

function parseURL () {const query = this.$root.$mp.query.queryif (query) {return JSON.parse(decodeURIComponent(query))} else {return {}}
}复制代码

以下是完整的MinRouter代码

const toString = Object.prototype.toString
function isObject (value) {return toString.call(value) === '[object Object]'
}
function isString (value) {return toString.call(value) === '[object String]'
}
function isDefault (value) {return value === void 0
}
function openPage (args) {let name, query = {}, queryStr = null, path, type, isName = falseswitch (true) {case isObject(args):({name, query = {}} = args)breakcase isString(args):name = argsbreakdefault:throw new Error('参数必须是对象或者字符串')}if (isObject(query)) {queryStr = encodeURIComponent(JSON.stringify(query))} else {throw new Error('query数据必须是Object')}this.$minRouter.forEach(item => {if (item.name === name) {path = item.pathtype = item.type || 'navigateTo'isName = true}})if (!isName) {throw new Error(`没有${name}页面`)}if (!['navigateTo', 'switchTab', 'reLaunch', 'redirectTo'].includes(type)) {throw new Error(`name:${name}里面的type必须是以下的值['navigateTo', 'switchTab', 'reLaunch', 'redirectTo']`)}return new Promise((resolve, reject) => {uni[type]({url: `/${path}?query=${queryStr}`,success: resolve,fail: reject})})
}
function parseURL () {const query = this.$root.$mp.query.queryif (query) {return JSON.parse(decodeURIComponent(query))} else {return {}
}}
function install (Vue) {Vue.mixin({beforeCreate: function () {if (!isDefault(this.$options.minRouter)) {Vue._minRouter = this.$options.minRouter}}})Object.defineProperty(Vue.prototype, '$minRouter', {get: function () {return Vue._minRouter._router}})Object.defineProperty(Vue.prototype, '$parseURL', {get: function () {return Vue._minRouter.parseURL}})Object.defineProperty(Vue.prototype, '$openPage', {get: function () {return Vue._minRouter.openPage}})}
function MinRouter (options) {if (!(this instanceof MinRouter)) {throw Error("MinRouter是一个构造函数,应该用`new`关键字调用")}isDefault(options) && (options = {})this.options = optionsthis._router = options.routes || []
}
MinRouter.install = install
MinRouter.prototype.openPage = openPage
MinRouter.prototype.parseURL = parseURL
export default MinRouter复制代码

使用方式如下

<template><view class="content"><image class="logo" src="/static/logo.png"></image><view><text class="title">{{title}}</text></view><button @click="toPage">跳转到我的页面</button></view>
</template>
<script>export default {data() {return {title: 'index'}},onLoad() {// 解析路由参数console.log(this.$parseURL())},methods: {toPage () {// 跳到my的页面  query是传递的参数this.$openPage({name: 'my',query: {id: 123}})}}}
</script>复制代码
<template><view class="content"><image class="logo" src="/static/logo.png"></image><view><text class="title">{{title}}</text></view><button @click="toPage">跳转到首页页面</button></view>
</template>
<script>export default {data() {return {title: 'my'}},onLoad() {// 解析路由参数console.log(this.$parseURL())},methods: {toPage () {// 跳到index的页面// 不传参数可以简写成如下this.$openPage('index')}}}
</script>复制代码

能不能和RouterLink一样使用

<router-link to="{name: 'my'}"></router-link>
<router-link to="my"></router-link>
<router-link to={name: 'my', query: {id: 123}}></router-link>复制代码

可以但是小程序不支持函数式组件,也就是不能一起封装到MinRouter

需要自己实现router-link

<template><div @click="openPage"><slot></slot></div>
</template>
<script>
export default {props: {to: {type: [Object, String],required: true}},methods: {openPage () {this.$openPage(this.to)}}
}
</script>复制代码

在main.js文件添加

import mina from './components/min-a.vue'
Vue.component('min-a', mina)复制代码

使用方式

<template><view class="content"><image class="logo" src="/static/logo.png"></image><view><text class="title">{{title}}</text></view><button @click="toPage">跳转到我的页面</button><min-a to="my">跳转到我的页面min-a标签跳转</min-a><min-a :to="{name: 'my', query: {id: 123}}">跳转到我的页面min-a标签跳转带参数</min-a></view>
</template>复制代码

到此完结

再聊聊

本来是有全局的beforeEach钩子函数的,但是觉得没什么用处就不要了

具体操作看github

基于uni-app的缓存器

转载于:https://juejin.im/post/5d0314a5f265da1ba77ca05b

uni-app路由的封装相关推荐

  1. uni app 开发微信小程序及上线体验

    uni app 开发微信小程序及上线体验 项目创建及微信小程序AppId的申请 本次开发的是电商类的微信小程序,这里用到的是HBuilderX这个编辑器.之前用的Visual Studio Code ...

  2. vant 验证手机号_【uni app】vant weapp的引入和部分详细调用(表单输入框、验证码、弹出层搭配选择器、地图)...

    本次小程序的开发使用uni app+vant weapp,vant weapp如何引用和部分组件使用方法如下 引入 在github(https://github.com/youzan/vant-wea ...

  3. uni app实现WIFI功能(只支持安卓APP)

    uni app实现WIFI功能 一.前言 二.使用 uni-WIFI 三.使用h5+ api 一.前言 最近需要在uniapp上实现WiFi功能,将个人的研究结果记录如下(都只支持安卓APP) 使用 ...

  4. uni app页面跳转后,刷新页面参数丢失问题

    正常页面路由跳转地址应该是这样的:http://localhost:8080/#/pages/study/hiring?id=1393112968202870785 浏览器刷新之后就编程这样子:htt ...

  5. 【翻译】基于 Create React App路由4.0的异步组件加载(Code Splitting)

    基于 Create React App路由4.0的异步组件加载 本文章是一个额外的篇章,它可以在你的React app中,帮助加快初始的加载组件时间.当然这个操作不是完全必要的,但如果你好奇的话,请随 ...

  6. 切换 uniapp_万能前端框架uni app初探03:底部导航开发

    前言 本节我们使用uni app的底部导航功能,点击不同tab会显示不同页面,这个功能在实际项目开发中几乎是必备的. 一.基础知识 1.tabBar 如果应用是一个多 tab 应用,可以通过 tabB ...

  7. uni app map 地图 漂浮问题及方案

    uni app map 地图 漂浮问题及方案 文章页有图片导致的问题,图片没加载出来,导致文章内容高度不固定,如果图片没加载出来,高度就是0,如果此时开始加载map,那么map就在那里加载,map原生 ...

  8. uni.app H5(微信公众号定位) uni.getLocation

    最近在开发公众号,由于之前经常使用uni,app写APP,索性就用uni.app来开发公众号了, 不过也遇到了一个问题,就是在公众号的首页要获取用户的定位.我看了看官网的API 有个uni.getLo ...

  9. react native Android端保持APP后台运行--封装 Headless JS

    react native Android端保持APP后台运行--封装 Headless JS 前些日子在做后台下载时踩了后台运行这个大坑,RN官网文档上面在安卓上提供了Headless JS方法,iO ...

  10. HBuilder X ——Uni app 学习笔记(一)

    HBuilder X --Uni app 学习笔记(一) 1.pages.json配置 *pages数组中第一项表示应用启动页,数组中其他项为项目中所有页面路径. enablePullDownRefr ...

最新文章

  1. Java初学者需掌握的4大核心基础知识
  2. java 聚合_Java聚合
  3. python3-numpy 数组操作--修改数组形状、翻转数组、修改数组维度、连接数组、分割数组、数组元素的添加与删除
  4. An impassioned circulation of affection(尺取+预处理)
  5. UVa-679 Dropping Balls(二叉树的编号)
  6. redhat7.3 superset的离线安装
  7. 【应用赏析】Las Vegas利用ParkPad(基于ArcPad)实现公园资产管理
  8. 病毒分析 - 特征码提取
  9. Unity3D开发游戏坦克大战
  10. nyoj 小明的存钱计划
  11. 浪潮存储加速国产替代
  12. html设置首页到尾页的按钮,AspNetPager里面的按钮(如:首页,上一页 下一页,尾页)如何更换为我想要的图片...
  13. 【开学季】30款高质量的自学网站,总有一款适合你
  14. 客户说:在忙,回头联系你。如何话术应对呢?
  15. 从截图里面识别数字_【答疑解惑】还没成功入驻数字工坊的同学看过来!!!
  16. vue中长时间未操作就会强制退出
  17. 蓝桥算法训练之素因子去重
  18. 献结程序员的一个故事——管道的故事
  19. 3D Instance Segmentation via Multi-Task Metric Learning
  20. 华为路由交换课程笔记12-AAA

热门文章

  1. Office报错:错误代码:30015-6(-1)
  2. 2 ELK收集nginx的json格式日志
  3. Linux禁止ping以及开启ping的方法
  4. win7下,令人头疼的 classpnp.sys (附带:安装系统时蓝屏;0x0000007b)。
  5. 解决RecyclerView的onClickListener问题
  6. vue-cli解决兼容ie的es6+api问题
  7. Xshell不能链接虚拟机(可ping通)--解决方案
  8. python解决高并发的方法
  9. 启动mysql时显示:/tmp/mysql.sock 不存在的解决方法
  10. 如何在Ubuntu Linux上安装JDK