手写vue路由

博客 动态
0 149
羽尘
羽尘 2022-05-16 09:59:17
悬赏:0 积分 收藏

手写vue路由

目录
  • 一、简易demo
  • 二、Vue-Router传参方式
  • 三、进阶-路由导航

一、简易demo
// routes注册import Vue from "vue";// import VueRouter from "vue-router";import VueRouter from "./vueRouter"; // 自定义路由 jsimport Home from "../views/Home.vue";Vue.use(VueRouter);const routes = [  {    path: "/",    name: "Home",    component: Home,  },  {    path: "/about",    name: "About",    // route level code-splitting    // this generates a separate chunk (about.[hash].js) for this route    // which is lazy-loaded when the route is visited.    component: () =>      import(/* webpackChunkName: "about" */ "../views/About.vue"),  },];const router = new VueRouter({  mode: "history",  routes,});export default router;
// vueRoutervar _Vue = nullexport default class VueRouter {  // 一、 install方法  static install(Vue) {    // 1、判断插件是否注册    if (VueRouter.install.installed) return    VueRouter.install.installed = true    // 2、将Vue构造函数记录到全局变量    _Vue = Vue    // 3、把创建Vue实例的时候传入的router对象注入到Vue实例上    // _Vue.prototype.$router = this.$options.router;    // 混入    _Vue.mixin({      beforeCreate() {        if (this.$options.router) {          _Vue.prototype.$router = this.$options.router          this.$options.router.init() // ?        }      }    })  }  //  二、构造函数  constructor(options) {    this.options = options    this.routeMap = {}    this.data = _Vue.observable({      current: '/'    })  }  init() {    this.createRouteMap()    this.initComponents(_Vue)    this.initEvent()  }  //   三、createRouteMap  createRouteMap() {    //   遍历所有的路由规则,把路由规则解析成键值对,保存在routeMap中    this.options.routes.forEach(route => {      this.routeMap[route.path] = route.component    })  }  //   四、initComponents  initComponents(Vue) {    Vue.component('router-link', {      props: {        to: String      },      //   template: '<a :href="to"><slot></slot></a>'      render(h) {        return h(          'a',          {            attrs: {              href: this.to            },            on: {              click: this.clickHandler            }          },          [this.$slots.default]        )      },      methods: {        clickHandler(e) {          history.pushState({}, '', this.to) // 修改地址栏 - 不会发送请求          this.$router.data.current = this.to // 重新加载响应的组件          e.preventDefault() // 阻止发送请求        }      }    })    const self = this    Vue.component('router-view', {      render(h) {        let component = self.routeMap[self.data.current]        return h(component)      }    })  }  //   五、返回按钮、前进按钮问题  initEvent() {    window.addEventListener('popstate', () => {      this.data.current = window.location.pathname    })  }}
二、Vue-Router传参方式

一、普通、动态路由传参方式

// 路由代码传参import About from 'about'// routes 配置{  path: '/about/:id', // 动态路由  component: About,  props: true // ①布尔模式}{  path: '/about', // 普通路由  component: 'About',  props: { id: 19 } // ②对象模式}// 接收方式 propsprops;['id'] 或者props: {  id: { type: Number, default: 12}}// ③函数模式routes:[  {    path: '/about',    component: About,    // props: route => ({id:route.query.id}) // url='/about?id="89"' 或者    props: route => ({id: route.params.id}) // url='/about/:id' => '/about/89'  }]

二、动态路由:将给定匹配模式的路由映射到同一个组件,复用一个组件,相对与销毁后重建更高效。

  • Keep-alive包括时,组件的声明周期钩子函数不会被重复调用。

  • 要对同一个组件中参数变化做出响应的话,可以通过watch 侦听$route对象上的任意属性

    watch: {  $route: {    immediate: true,    handler(route) {      // 处理事件 对路由变化做出响应    }  }}
  • 或者使用导航守卫,beforeRouteUpdate,也可以取消导航

三、捕获所有路由或404路由

四、路由的匹配语法

  • 自定义正则 像可以区分 /list/100 和/list/xsk 等路由

    • routes: [ { path: '/list/:id(\\d+)'}, {path: '/list/:name'} ]
  • 可以重复的参数 匹配多个部分的路由,可以用 * 号和 +号将参数标记为重复

  • 也可通过使用?号修饰符(0个或1个)将一个参数标记为可选

五、嵌套路由、命名路由

六、编程式导航

  • 声明式()\编程式路由 router.push(...)

  • Router.push(params):

    • Params: 字符串路径、路径对象、命名的路由并加上参数、带查询参数、带hash

    •   '/users/detail'  { path: '/users/detail' }  { name: 'detail', params: {id: '0'}}  { path: '/users/detail', query: {id: '0'} }
  • 替换当前位置 router.replace({path: '/users'}) 或者router.push({path:'users', replace: true}); 导航时不会向history添加记录

  • history.go()横跨历史

七、命名视图:

八、重定向配置

// 通过routes配置来完成const routes = [{ path: '/home', redirect: '/'}]// 重定向的目标也可以是一个命名的路由  redirect: { name: 'Details'}// 一个方法动态返回重定向目标const routes = [  {    path: '/home/:id',    redirect: to => {      return {path:'Details', query: { q: to.params.searchText}}    }  }]// 别名alias: '/home'

九、路由组件传参 props、$route.query$route.params

  • 布尔模式 routes配置时 props:true设置即可

  • 对象模式 props: { id: '0' } 当props为静态的时候很有用

  • 函数模式 创建一个返回props的函数,允许你将参数转换为其他类型,将静态值与基于路由的值相结合等操作

    props: route => ({ query: route.query.id })props: route => ({ params: route.params.id})
  • 对于命名视图的路由,必须为每个命名视图定义props配置

    const routes = [{  path: '/home',  components: { default: Home, sidebar: Sidebar},  props: { default: true, sidebar: true}}]

十、不同的历史模式

  • Hash模式:history: createWebHashHistory() SEO受影响
  • HTML5模式:history:createWbeHistory() 如果没有适当的服务器配置,就会404,需要在服务器上添加一个简单的回退路由
三、进阶-路由导航

一、导航守卫:vue-router提供的主要是通过跳转或取消的方式守卫导航。

  • 方式:全局、单个路由独享、组件

  • 全局前置守卫:beforeEnter:

    • 每个守卫都接收两个__参数__:to\from\next(可选)
    • 返回值 ①false:取消当前导航、②一个路由地址:通过一个路由地址跳转到不同的地址,类似于router.push()可配置,当前的 导航被中断然后进行一个新的导航。
    • next可选参数
  • 全局后置守卫:afterEach 不接受next函数也不会改变导航本身

  • 全局解析守卫:beforeResolve

  • 路由独享守卫:在routes中配置

  • 组件内的守卫 可用配置API:beforeRouteEnter、beforeRouteUpdate、beforeRouteLeave

    • beforeRouteEnter:唯一可传递next回调守卫;解决不可访问this;
    • next()里的内容执行时机在组件mounted周期之前;
    • beforeRouteUpdate: 该组件复用时被调用
posted @ 2022-05-16 09:54 xsk-walter 阅读(0) 评论(0) 编辑 收藏 举报
回帖
    羽尘

    羽尘 (王者 段位)

    2335 积分 (2)粉丝 (11)源码

     

    温馨提示

    亦奇源码

    最新会员