vue路由的使用

120 阅读3分钟

混入(mixin)

全局混入

全局混入后,就是之后所有的组件和vue的创建都会被混入到。

如下代码混入的方式:

Vue.mixin({
  created(){
    var myOption=this.$options.myOption;
    console.log("xxx");
    if(myOption){
      console.log(myOption);
    }
  }
});

这个代码之后,所有只要有关于create这个生命周期都会自动添加,如果重复则以组件的为准。

实现VueRouter

Vue实例传入的参数是如何进行操作的:

创建Vue实例时传入的{} 是绑定在this.$options中的。

new Vue({
  router,//这个属性是挂载当了当前this.$options中的,写在{...}对象里的内容都是挂载到$options这个变量里的
  store,
  render: h => h(App)
}).$mount('#app');

如下截图:

所以可以通过是否包含router属性来判断是根组件还是子组件。

MVueRouter作为一个插件的方式存在

如下代码:

let Vue;

class MVueRouter{
    constructor(o){
      console.log("执行了构造函数方法");
      this.$o=o;  
    }
}

MVueRouter.install=function(_Vue){

    //保存构造函数再MVue中使用
    Vue=_Vue;
    //挂载$router
    //获取根实例中的router选项
    Vue.mixin({
        beforeCreate(){
            //如果存在则说明是根实例
            if(this.options.router){
                Vue.prototype.$router=this.options.router;
            }
        }
    });
}
export default MVueRouter;

上述代码在router/index.j下的运行是:

import Vue from 'vue'
import MVueRouter from "./mrouter";

Vue.use(MVueRouter);

let rotes=[
  {
		
  }
];

let router=new MVueRouter({
  mode:"history",
  base:process.env.BASE_URL,
  rotes
});

export default router;

然后把上述router到处去,给main.js作为属性挂载上去。

分析:

1,上边代码是自定义的路由文件。MVueRouter

2,加载到main.js文件,执行Vue.use();这样就是执行了,该类的install方法。

3,install的mixin进行混入,混入的beforeCreate钩子。之所以要写beforeCreate钩子是等Vue根组件创建时执行它的beforeCreate钩子函数,才会挂载第四步的操作。

4,在组件中传入的参数{}都是挂载到options中的,但是只有根组件中是有router这个属性的,所以只有根组件的属性options中的,但是只有根组件中是有router这个属性的,所以只有根组件的属性options中有router属性。然后在根组件中的beforeCreate钩子中完成router绑定在Vue原型上。这样,Vue的实例和this都都能够访问到router这个属性,而router这个属性的值是我们自己写的路由组件MVueRouter在router/index.js下创建的一个对象;

想一想它的设计模式:

给一个A设计一个方法,当执行到A的某个方法并且满足条件时,对A或者外边的某个类做一个具体的功能,可以充分的利用this这个关键字。

实现router-link和router-view

vue的两个版本

完整版是vue.js(包含compier) 和 非完整版(不包含compier) vue.runtime.js 非完整版是没有解析器的是不能够解析template结构的。只能用render进行渲染。

vue.js 是html渲染

vue.runtime.js是js渲染,vue-cli默认是这个。

router-link

全局组件。

这里使用非完整版vue.js实现的。

第一步是如下,router-link标签里边默认是a元素,以及属性和内容。

是在MVueRouter的install方法中实现的。

 Vue.component("router-link",{
        props:{
            to:{
                type:String,
                required:true
            }
        },
        render(h){
            console.log(this);
            return h("a",
            {
                attrs:{
                    href:"#"+this.to
                }
            },
            //这个组件里边匿名的子元素
            this.$slots.default);

        }
    });

router-view的实现

router-view是显示组件。

组件的显示是根据地址栏的hash值操作的。

可以监听地址栏的hash值的变化。

在路由构造器中进行的监听的实现。

代码如下:

      //定义一个变量,默认是根路径
      this.current="/";

      window.addEventListener("hashchange",function(){
          this.current=window.location.hash.slice(1);
      })

找到hash值后,通过hash值与组件对应的容器里边找到组件,然后进行显示。hash值与组件对应的容器在vue-router中是写在rotes里边的。如下代码的实现:

Vue.component("router-view",{
        render(h){
            //定义一个当前的组件
            let comp=null;
            //存储hash与组件对应的容器中找到组件并且进行显示即可
            //遍历容器,找到对应的组件
            this.$router.$o.rotes.forEach(route=>{
                if(this.$router.current===route.path){
                    //找到后赋值当前组件变量进行存储
                     comp=route.component;
                }
            });
            return h(comp)
        }
    });

这样就实现了,hash值的变化,改变组件的显示。

如何实现router-view的响应式

我们可以通过不同的hash值,获取到不同的组件。但是组件不会自动更新,也就不是不会自动进行render函数的渲染。

也就是我们需要做一个操作就是当hash值发生改变时,就要执行全局组件router-view的render函数。

vue给我们提供了一个方法是可以实现的。

因为render函数中,只要是有响应式属性存在就会重新进行渲染的。

如下的几个方法都是可以让属性变成响应式属性的:

这个是一个新的方法:还有Vue.set() 或者new 一个新的Vue等方法。

    Vue.util.defineReactive(this,"current","/");