草庐IT

手写vue路由

xsk-walter 2023-03-28 原文

一、简易demo
// routes注册
import Vue from "vue";
// import VueRouter from "vue-router";
import VueRouter from "./vueRouter"; // 自定义路由 js
import 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;
// vueRouter
var _Vue = null

export 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 } // ②对象模式
}

// 接收方式 props
props;['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: 该组件复用时被调用

有关手写vue路由的更多相关文章

  1. ruby-on-rails - Rails 3 中的多个路由文件 - 2

    Rails2.3可以选择随时使用RouteSet#add_configuration_file添加更多路由。是否可以在Rails3项目中做同样的事情? 最佳答案 在config/application.rb中:config.paths.config.routes在Rails3.2(也可能是Rails3.1)中,使用:config.paths["config/routes"] 关于ruby-on-rails-Rails3中的多个路由文件,我们在StackOverflow上找到一个类似的问题

  2. ruby - rails 3 redirect_to 将参数传递给命名路由 - 2

    我没有找到太多关于如何执行此操作的信息,尽管有很多关于如何使用像这样的redirect_to将参数传递给重定向的建议:action=>'something',:controller=>'something'在我的应用程序中,我在路由文件中有以下内容match'profile'=>'User#show'我的表演Action是这样的defshow@user=User.find(params[:user])@title=@user.first_nameend重定向发生在同一个用户Controller中,就像这样defregister@title="Registration"@user=Use

  3. ruby-on-rails - Rails 3,嵌套资源,没有路由匹配 [PUT] - 2

    我真的为这个而疯狂。我一直在搜索答案并尝试我找到的所有内容,包括相关问题和stackoverflow上的答案,但仍然无法正常工作。我正在使用嵌套资源,但无法使表单正常工作。我总是遇到错误,例如没有路线匹配[PUT]"/galleries/1/photos"表格在这里:/galleries/1/photos/1/edit路线.rbresources:galleriesdoresources:photosendresources:galleriesresources:photos照片Controller.rbdefnew@gallery=Gallery.find(params[:galle

  4. 计算机毕业设计ssm+vue基本微信小程序的小学生兴趣延时班预约小程序 - 2

    项目介绍随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱小学生兴趣延时班预约小程序的设计与开发被用户普遍使用,为方便用户能够可以随时进行小学生兴趣延时班预约小程序的设计与开发的数据信息管理,特开发了小程序的设计与开发的管理系统。小学生兴趣延时班预约小程序的设计与开发的开发利用现有的成熟技术参考,以源代码为模板,分析功能调整与小学生兴趣延时班预约小程序的设计与开发的实际需求相结合,讨论了小学生兴趣延时班预约小程序的设计与开发的使用。开发环境开发说明:前端使用微信微信小程序开发工具:后端使用ssm:VU

  5. ruby-on-rails - Rails - 从命名路由中提取 HTTP 动词 - 2

    Rails中有没有一种方法可以提取与路由关联的HTTP动词?例如,给定这样的路线:将“users”匹配到:“users#show”,通过:[:get,:post]我能实现这样的目标吗?users_path.respond_to?(:get)(显然#respond_to不是正确的方法)我最接近的是通过执行以下操作,但它似乎并不令人满意。Rails.application.routes.routes.named_routes["users"].constraints[:request_method]#=>/^GET$/对于上下文,我有一个设置cookie然后执行redirect_to:ba

  6. ruby-on-rails - 如何在 Rails 中设置路由的默认格式? - 2

    路由有如下代码:resources:orders,only:[:create],defaults:{format:'json'}resources:users,only:[:create,:update],defaults:{format:'json'}resources:delivery_types,only:[:index],defaults:{format:'json'}resources:time_corrections,only:[:index],defaults:{format:'json'}是否可以使用1个字符串为所有资源设置默认格式,每行不带“默认值”散列?谢谢。

  7. ruby - cucumber 的路由问题 - 2

    我正在使用rails3和cucumber,除了这个小问题,一切都很顺利GivenIamonthe"editautomobile"pageNoroutematches{:controller=>"automobiles",:action=>"edit"}(ActionController::RoutingError)现在路径在paths.rb中设置为edit_automobile_path在routes.rb中我有汽车作为资源,我搭建了它所以请告诉我我遗漏了什么,清楚地定义了路线并且匹配,因为我运行了rake路线并看到了路线。请指出正确的方向 最佳答案

  8. ruby - Rails 路由 : Giving default values for path helpers - 2

    有什么方法可以为url/path助手提供默认值吗?我有一个可选范围环绕我的所有路线:#config/routes.rbFoo::Application.routes.drawdoscope"(:current_brand)",:constraints=>{:current_brand=>/(foo)|(bar)/}do#...allotherroutesgohereendend我希望用户能够使用这些URL访问网站:/foo/some-place/bar/some-place/some-place为了方便起见,我在我的ApplicationController中设置了一个@current

  9. ruby-on-rails - 将 Rails 路由助手作为类方法添加到类中 - 2

    我如何将像“root_path”这样的Rails路由助手作为类方法添加到像my_model.rb这样的类中?所以我的课是这样的:ClassMyModeldefself.fooreturnself.root_pathendendMyModel.foo以上不起作用,因为ClassMyModel不响应root_path这是我所知道的:我可以使用includeRails.application.routes.url_helpers,但这只会将模块的方法添加为实例方法我试过扩展Rails.application.routes.url_helpers但它没用请随时给我上课:)

  10. ruby-on-rails - 获取 ActionController::RoutingError(当尝试使用 AngularJS 将数据发布到 Rails 服务器时,没有路由匹配 [OPTIONS] "/users" - 2

    尝试从我的AngularJS端将数据发布到Rails服务器时出现问题。服务器错误:ActionController::RoutingError(Noroutematches[OPTIONS]"/users"):actionpack(4.1.9)lib/action_dispatch/middleware/debug_exceptions.rb:21:in`call'actionpack(4.1.9)lib/action_dispatch/middleware/show_exceptions.rb:30:in`call'railties(4.1.9)lib/rails/rack/logg

随机推荐