Update the content

  1.  Configure the routing
    1. In previous versions, routes need to be manually configured. After the version is updated, routes are automatically configured
  2. Adding global Hooks
    1. Global hooks were left out for performance reasons
    2. The corresponding hooks will be added after the update
  3. (= &? And other special characters will not support route transmission parameters, you can handle
    1. encodeURIComponent
    2. decodeURIComponent

  4. The new Router usage mode

    Navigate: [‘navigateTo’, ‘switchTab’, ‘reLaunch’, ‘redirectTo’]

    usage

    // File directory pages/home/index.vueexport default {
      navigate: ['navigateTo'} // The name of the folder (home) is generated.export default {
      navigate: ['navigateTo'.'switchTab'// navigateTo (home) // switchTab (home) // navigateTo (home Name of the folder (swhOME) // Other values // reLaunch name is the name of the folder (relhome) // redirectTo Name is the name of the folder (redhome)Copy the code

    this.$minRouter.push({// name here corresponds to the generated name value name above:'home'Params: {id: 1}}); // This is the type of page to pass the parameter.$minRouter.push('swhome') // Get the page parameter this.$parseURL() // Go back to page this.$minRouter.back(-1)Copy the code

    File directory router/index.js in the project

    Route interception can be set to use similarly to Vue global front hooks

  5. Specific seegithub


Uni-app provides the routing function for page hopping, but we still found some inconvenient points in the process of using it, as shown in the following figure:



What are the problems with page jumps

  1. Bad page path management problem
    1. Why is it difficult to manage: changing the page path, or not having to find changes when subcontracting
  2. The way parameters are passed is not very friendly
    1. Why not: Need to manually concatenate parameter lists
  3. The parameter type is single and only string is supported
    1. Whether you pass string or number or Boolean, you get a string
  4. Parameters truncated when passing special characters (e.g. qr code information)
    1. The reason is that (=&?) cannot be included. And other special characters

Create a project




Create a file (router.js) for centralized management under the directory structure

The following code

exportDefault {// home page index:'/pages/index/index.vue', // my page is my:'/pages/my/index.vue'
}Copy the code

It looks like this when you use it

<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>Copy the code

Router.js is a hassle to import when using router.js

Let’s look at the second and third questions

Let’s look at an example

If you have a lot of parameters, this is really not a good way to operate. Can you separate out the parameter part and concatenate it to the URL?

Surprised to find that the number passed turned into a string, the parameter is not true

I’m not going to show you the fourth problem

So without further ado, I believe that you should also understand the problems, and let’s solve them.

First create a file (minrouter.js) directory structure as follows



The following code solves the first problem

It is no longer necessary to import the router.js file

import urlSet from './router';
function openPage (url) {  
    uni.navigateTo({
        url: `${urlSet[url]}`})}export default openPageCopy the code

The main.js file is modified as follows

import Vue from 'vue'
import App from './App'/ / introduce MinRouter file import openPage from'./MinRouter'
Vue.config.productionTip = false
App.mpType = 'app'OpenPage = openPage const app = new Vue({... App }) app.$mount(a)Copy the code

use

<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>Copy the code

Let’s deal with the second and third questions

The third problem is that if you want to pass a number, whatever you pass will become a string.

Is there a way to turn data into a string and still restore it to its original type?

Using JSON solves the above problem, and the second problem is well addressed

Try modifying the original code

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

use

<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>Copy the code

Let’s tackle the fourth problem

(= &? And other special characters in the URL above is special meaning, so we need to encode json string

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

All the above problems have been solved, but the feeling is still not good. Could you package it into a Vue plug-in, similar to VueRouter

The answer is yes

Packaging molding MinRouter

Change the router.js file to the following

import MinRouter from './MinRouter'Const router = new MinRouter({routes: [{routes: [{//'pages/index/index',
      name: 'index'
    },
    {
      path: 'pages/my/index',
      name: 'my'}]})export default routerCopy the code

Change the main.js file to the following

import Vue from 'vue'
import App from './App'/ / introduce MinThe Router file import MinRouter from './MinRouter'// Import router file import minRouter from'./router'
Vue.config.productionTip = falseVue. Use (MinRouter)
App.mpType = 'app'const app = new Vue({ ... App, minRouter }) app.$mount(a)Copy the code

The above code configuration already looks like VueRouter

Add the following code to the MinRouter file

const toString = Object.prototype.toStringfunction
 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 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 is a constructor and should be called with the 'new' keyword.")
  }
  isDefault(options) && (options = {})
  this.options = options
  this._router = options.routes || []
}
MinRouter.install = install
export default MinRouterCopy the code

Let’s set the openPage parameters

Name: indicates the page to be jumped

Query: parameter used to jump to the page

OpenPage ({name: jump page, query: {id: 123}})Copy the code

The openPage function is as follows

function openPage (args) {
  let {name, query = {}} = args
  let queryStr = null, path
  queryStr = 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
    })
  })
}Copy the code

this.$minRouterThe code above has been proxy, do not feel surprised, in fact, is the configuration of routes in the routeCopy the code

The above only route can only be navigateBack this way

You may want to add a parameter to control the route, but it is not easy. Since the openPage function cannot be added, can it be added to the route?

Let’s modify the router.js file

import MinRouter from './MinRouter'Const router = new MinRouter({routes: [{routes: [{//'pages/index/index', / /typeMust be the following values ['navigateTo'.'switchTab'.'reLaunch'.'redirectTo'] // Redirect (default redirect)type: 'navigateTo',
      name: 'index'
    },
    {
      path: 'pages/my/index',
      name: 'my'}]})export default routerCopy the code

The openPage function is as follows

function openPage (args) {
  let name, query = {}, queryStr = null, path, type
  switch (true) {
    case isObject(args):
      ({name, query = {}} = args)
      break
    case isString(args):
      name = args
      break
    default:
      throw new Error('Parameter must be an object or a string')}if (isObject(query)) {
    queryStr = encodeURIComponent(JSON.stringify(query))
  } else {
    throw new Error('Query data must be Object')
  }
  this.$minRouter.forEach(item => {
    if (item.name === name) {
      path = item.path
      type = item.type || 'navigateTo'}})if(! ['navigateTo'.'switchTab'.'reLaunch'.'redirectTo'].includes(type)) {
    throw new Error(`name:${name}The inside of thetypeMust be the following values ['navigateTo'.'switchTab'.'reLaunch'.'redirectTo']`)
  }
  return new Promise((resolve, reject) => {
    uni[type]({
      url: `/${path}? query=${queryStr}`,
      success: resolve,
      fail: reject
    })
  })
}Copy the code

How to parse routing parameters

The following functions parse the route parameters

function parseURL () {
  const query = this.$root.$mp.query.query
  if (query) {
    return JSON.parse(decodeURIComponent(query))
  } else {
    return{}}}Copy the code

Here is the complete MinRouter code

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 = false
  switch (true) {
    case isObject(args):
      ({name, query = {}} = args)
      break
    case isString(args):
      name = args
      break
    default:
      throw new Error('Parameter must be an object or a string')}if (isObject(query)) {
    queryStr = encodeURIComponent(JSON.stringify(query))
  } else {
    throw new Error('Query data must be Object')
  }
  this.$minRouter.forEach(item => {
    if (item.name === name) {
      path = item.path
      type = item.type || 'navigateTo'
      isName = true}})if(! IsName) {throw new Error(' No${name}Page `)}if(! ['navigateTo'.'switchTab'.'reLaunch'.'redirectTo'].includes(type)) {
    throw new Error(`name:${name}The inside of thetypeMust be the following values ['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.query
  if (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 is a constructor and should be called with the 'new' keyword.")
  }
  isDefault(options) && (options = {})
  this.options = options
  this._router = options.routes || []
}
MinRouter.install = install
MinRouter.prototype.openPage = openPage
MinRouter.prototype.parseURL = parseURL
export default MinRouterCopy the code

Use as follows

<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() {// parse the route parameter console.log(this).$parseURL())
    },
    methods: {
      toPage() {// skip to my page query is the argument passed this.$openPage({
          name: 'my',
          query: {id: 123}
        })
      }
    }
  }
</script>Copy the code

<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() {// parse the route parameter console.log(this).$parseURL())
    },
    methods: {
      toPage() {// skip to index page // No arguments can be abbreviated as this.$openPage('index')
      }
    }
  }
</script>Copy the code