uni-app路由的封装
uni-app提供了路由功能来实现页面跳转,但是在使用的过程中我们还是发现有些不方便的地方,如下图:
页面的跳转存在哪些问题呢
- 页面路径不好的管理问题
- 为什么不好管理:就是改页面路径,或者说分包的时候不用一个个找着改
- 传递参数的方式不太友好
- 为什么不友好:需要手动拼接参数列表
- 参数类型单一,只支持string
- 不管传string还是number和boolean得到的都是字符串
- 传特殊字符时会发现参数被截断(比如传二维码信息)
- 原因是不能包括(=&?)等特殊字符
首先先做一下准备工作
创建一个项目
代码如下
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路由的封装相关推荐
- uni app 开发微信小程序及上线体验
uni app 开发微信小程序及上线体验 项目创建及微信小程序AppId的申请 本次开发的是电商类的微信小程序,这里用到的是HBuilderX这个编辑器.之前用的Visual Studio Code ...
- vant 验证手机号_【uni app】vant weapp的引入和部分详细调用(表单输入框、验证码、弹出层搭配选择器、地图)...
本次小程序的开发使用uni app+vant weapp,vant weapp如何引用和部分组件使用方法如下 引入 在github(https://github.com/youzan/vant-wea ...
- uni app实现WIFI功能(只支持安卓APP)
uni app实现WIFI功能 一.前言 二.使用 uni-WIFI 三.使用h5+ api 一.前言 最近需要在uniapp上实现WiFi功能,将个人的研究结果记录如下(都只支持安卓APP) 使用 ...
- uni app页面跳转后,刷新页面参数丢失问题
正常页面路由跳转地址应该是这样的:http://localhost:8080/#/pages/study/hiring?id=1393112968202870785 浏览器刷新之后就编程这样子:htt ...
- 【翻译】基于 Create React App路由4.0的异步组件加载(Code Splitting)
基于 Create React App路由4.0的异步组件加载 本文章是一个额外的篇章,它可以在你的React app中,帮助加快初始的加载组件时间.当然这个操作不是完全必要的,但如果你好奇的话,请随 ...
- 切换 uniapp_万能前端框架uni app初探03:底部导航开发
前言 本节我们使用uni app的底部导航功能,点击不同tab会显示不同页面,这个功能在实际项目开发中几乎是必备的. 一.基础知识 1.tabBar 如果应用是一个多 tab 应用,可以通过 tabB ...
- uni app map 地图 漂浮问题及方案
uni app map 地图 漂浮问题及方案 文章页有图片导致的问题,图片没加载出来,导致文章内容高度不固定,如果图片没加载出来,高度就是0,如果此时开始加载map,那么map就在那里加载,map原生 ...
- uni.app H5(微信公众号定位) uni.getLocation
最近在开发公众号,由于之前经常使用uni,app写APP,索性就用uni.app来开发公众号了, 不过也遇到了一个问题,就是在公众号的首页要获取用户的定位.我看了看官网的API 有个uni.getLo ...
- react native Android端保持APP后台运行--封装 Headless JS
react native Android端保持APP后台运行--封装 Headless JS 前些日子在做后台下载时踩了后台运行这个大坑,RN官网文档上面在安卓上提供了Headless JS方法,iO ...
- HBuilder X ——Uni app 学习笔记(一)
HBuilder X --Uni app 学习笔记(一) 1.pages.json配置 *pages数组中第一项表示应用启动页,数组中其他项为项目中所有页面路径. enablePullDownRefr ...
最新文章
- Java初学者需掌握的4大核心基础知识
- java 聚合_Java聚合
- python3-numpy 数组操作--修改数组形状、翻转数组、修改数组维度、连接数组、分割数组、数组元素的添加与删除
- An impassioned circulation of affection(尺取+预处理)
- UVa-679 Dropping Balls(二叉树的编号)
- redhat7.3 superset的离线安装
- 【应用赏析】Las Vegas利用ParkPad(基于ArcPad)实现公园资产管理
- 病毒分析 - 特征码提取
- Unity3D开发游戏坦克大战
- nyoj 小明的存钱计划
- 浪潮存储加速国产替代
- html设置首页到尾页的按钮,AspNetPager里面的按钮(如:首页,上一页 下一页,尾页)如何更换为我想要的图片...
- 【开学季】30款高质量的自学网站,总有一款适合你
- 客户说:在忙,回头联系你。如何话术应对呢?
- 从截图里面识别数字_【答疑解惑】还没成功入驻数字工坊的同学看过来!!!
- vue中长时间未操作就会强制退出
- 蓝桥算法训练之素因子去重
- 献结程序员的一个故事——管道的故事
- 3D Instance Segmentation via Multi-Task Metric Learning
- 华为路由交换课程笔记12-AAA
热门文章
- Office报错:错误代码:30015-6(-1)
- 2 ELK收集nginx的json格式日志
- Linux禁止ping以及开启ping的方法
- win7下,令人头疼的 classpnp.sys (附带:安装系统时蓝屏;0x0000007b)。
- 解决RecyclerView的onClickListener问题
- vue-cli解决兼容ie的es6+api问题
- Xshell不能链接虚拟机(可ping通)--解决方案
- python解决高并发的方法
- 启动mysql时显示:/tmp/mysql.sock 不存在的解决方法
- 如何在Ubuntu Linux上安装JDK