vue-router实现原理及基础复习

282 阅读3分钟

一:vue-router基本使用

  1. 在router文件中的index.js文件

  2. 在router文件中的index.js中导入vue和vue-router

  3. 通过Vue.use(VueRouter)进行注册

  4. 创建路由对象 const router = new VueRouter({router})

  5. 配置路由规则 const router = [{},{},{}]

  1. 在main.js文件中
  2. 导入在router中的index.js导出的路由对象
  3. 在创建vue实例的时候注册router对象(在vue实例对象中注册是因为在vue实例中创建注入routerrouter和route两个属性方法)

  1. 在app.vue文件中
  2. 使用router-view作为占位符

二:动态路由

  1. 路由按需加载   const  'name'  = () => import('路径')
  2. 例如(path :'./detail/:id')  获取路由id
  3. 方式一:this.route.params.id this.route.params.id  || this.route.query.id
  4. 方式二:在配置路由时开启props(props:true),会把URL中的参数传递给组件,在组件中通过props来接受URL参数

三:嵌套路由

  1. 相同部分使用相同的代码,不同的部分使用router-view进行占位
  2. 子路由:children

四:编程式导航

  1. this.$router
  2. push会记录历史
  3. replace不会记录历史记录
  4. go跳转到历史位置
  5. 传参方式一:this.$router.push({name:'路径',params:{id:1}})
  6. 传参方式二:this.$router.push({path:'路径',query:{id:2}})
  7. 两者的区别是浏览器url地址后面是否看以看见

五:Hash模式和History模式的区别

  1. 表现形式的区别
  2. Hash模式路径中带着#号,?号后面携带参数
  3. History模式和Hash不同的是么有# ?
  4. 原理区别
  5. Hash模式是基于描点以及onhashchange事件
  6. History模式是基于HTML5中的History API
  7. history.pushState()和history.replaceState()

六:History模式

  1. History模式需要服务器的支持
  2. 在单页面应用中,服务器不存在http:www.texturl.com/login这样的地址会…
  3. 在服务端应该除了静态资源外都返回单页面应用的index.html
  4. 在创建VueRouter时需要添加(mode:'history')
  5. vue-cli服务器自带配置好了history模式

七:VueRouter实现原理

  1. 前置知识

  2. 插件

  3. 混入

  4. Vue.observable

  5. 插槽

  6. render函数

  7. 运行时和完整版的Vue

  8. hash模式(location.url)(#后面的地址发送变化改变浏览器不会向服务器发送请求,会把历史记录记录到浏览器中)

  9. URL中#后面的内容作为路径地址

  10. 监听hashChange事件

  11. 根据当前路由地址找到相对应组件重新渲染

  12. History模式(浏览器不会向服务器发送请求)

  13. 通过history.pushState()方法改变地址栏

  14. 监听popstate事件(点击浏览器的返回或者前进和go才会触发)

  15. 根据当前路由地址找到相对应组件重新渲染

八:VueRouter模拟实现-分析

  1. Vue.use可以传入函数或者对象,如果传入的是函数,Vue.use内部会直接调用这个函数,如果传入的是一个对象,Vue.use内部会调用这个对象的install方法

  1. 第一个框是名字

  2. -第二个框是属性

  3. 第三个框是方法_代表静态方法

九:VueRouter-install

  1. 使用cli脚手架创建一个项目,带路由

  2. 在src目录下面创建一个vuerouter文件夹存储模块

  3. 在vuerouter文件夹中创建index.js文件

    let _Vue = null //导出一个类 export default class VueRouter { //定义一个install静态方法,传入Vue的构造函数 static install(Vue){ //1.判断当前创建是否安装 //installed是自己增加的属性,true代表已安装 if(VueRouter.install.installed){ return } VueRouter.install.installed = true //2.把Vue构造函数记录到全局变量(因为vuerouter的实例方法中使用这个Vue的构造函数) _Vue = Vue //3.把创建Vue实例时候传入的router对象注入到Vue实例上 //使用混入 _Vue.mixin({ beforeCreate(){ //防止多次判断(判断是否存在路由) if(this.options.router){ _Vue.prototype.router = this.$options.router } } }) } }

十:VueRouter-构造函数

constructor(options){
   //初始化3个值
   //作用是记录这个对象传入的options
   this.options = options
   //这个对象是将options中传入的router(规则)解析出来存储到routerMap对象里
   this.routerMap = {}
   //这是一个响应式的对象(使用vue中提供的observable,他会转换为响应式的对象)
   this.data = _Vue.observable({
   //作用是存储当前的路由地址,现在的value是默认情况
       current:'/'
   })
}

十一:VueRouter-createRouterMap

  1. 作用是把构造函数传过来的选项中的router,转换成键值的形式存储到构造函数中的routerMap中

    createRouterMap(){ //遍历所有的路规则,把路由规则解析成键值对的形式存储到routerMap对象中 //routes(这是存放路由地址的数组) this.options.routes.forEach( route => { this.routerMap[route.path] = route.component }) }

十二:VueRouter-router-link

  1. 运行时会报错,因为是Vue运行时的版本,不支持template模板

  2. 可以使用完整版的Vue或者render函数解决

    Home About

    //接收一个Vue的构造函数作为参数 initComponents(Vue){ //使用vue创建组件 //名字,选项 Vue.component('router-link',{ props:{ to:String }, template:'' }) }

//作用是将下面两个方法包装起来
init(){
     this.createRouterMap()
     this.initComponents(_Vue)
     this.initEvent()
}

_vue.mixin({
   beforeCreate(){
       //防止多次判断
       if(this.$options.router){
          _Vue.prototype.$router = this.$options.router
          //调用init方法
          this.$options.router.init()
        }
   }
})

十三:VueRouter-完整版的Vue

  1. 运行时版:不支持template模板,需要打包的是否提前编译

  2. 完整版:包含运行时和编译器,体积比运行时版打10K左右,程序运行的时候把模板转换成render函数

  3. 创建vue.config.js文件

  4. module.exports = { runtimeCompiler:true }

    module.exports = { runtimeCompiler : true }

十四:VueRouter-完整版的render

initComponents(Vue){
  Vue.component('router-link',{
     //接收外部传来的参数
     props:{
        to : String,
     },
     //h函数的作用是帮我们创建虚拟DOM
     render(h){
       //这个h函数是vue传来的
       //第一个参数是我们要创建的这个元素对应的选择器(例如标签选择器)
       //第二个参数可以给这个标签设置一些元素
       //第三个参数可以设置我们生成元素的子元素
       return h(
         "a",{
             //通过attrs来设置属性
             attrss:{
               href:this.to
             },
             //router-view
             on:{
                //注册点击事件
                click: this.clickGandler
             }
         },
         //这是a标签里面的内容,可以是多个所以是数组
         //这种写法是获取默认插槽的内容
         [this.$slots.default]
       )
     },
     //router-view阻止点击事件
     methods: {
       clickGandler(e){
         //第一个参数data,第二个参数stitle,第三个参数是url
         history.pushState({},'',this.to)
         //加载对应组件(让下面重新渲染视图)
         this.$router.data.current = this.to
         e.preventDafault()
       }
     }
  })
}

十五:VueRouter-router-view

initComponents(Vue){
const self = this
Vue.component("router-view",{
   render(h){
     //当前路由组件
     const component = self.routerMap[self.data.current]
     //使用h函数把组件转换为虚拟DOM
     return h(component)
   }
})
}

十六:VueRouter-initEvent

  1. 解决浏览器前进后退按钮点击地址栏发送变化但是视图未发送变化的问题

  2. 调用popstate

    initEvevt(){ //浏览器前进后退功能 window.addEventListener('popstate',() => { this.data.current = window.location.pathname }) }