vue-router

vue-router 是vue.js的官网路由管理器.它和vue.js外围深度集成.让构建单页面利用大海捞针

应用步骤

(1) 装置 vue add router
(2) 应用vue-router插件

import Router from 'vue-router'Vue.use(Router)

(3) 创立Router实例 router.js

export default new Router({...})

(4) 在根组件上增加该实例 main.js

import Router from './router'new Vue({    router,}).$mount("#app");

(5) 增加路由视图 App.vue

<router-view></router-view>

(6) 路由导航

<router-link to="/">Home</router-link>this.$router.push('/')

vue-router 源码简略实现

单页面程序中,url发生变化的时候,不刷新页面,显示对应视图

需要剖析

(1) 页面不刷新

hash模式  #/about

(2) 页面视图发生变化

router-view相应式数据: url地址发生变化,找到对应的组件 动静从新执行         render

工作实现一个插件

(1) 实现一个vueRouter类解决路由选项监控url变动, hashchange响应这个变动(2) 实现install办法$router注册两个全局组件  router-link  router-view

实现一个插件:创立VueRouter类和install办法

创立kvue-router.js

let Vue; // 援用构造函数, vueRouter中要应用class VueRouter {    constructor(options) {        this.$options = options;    }}// 插件实现install办法, 注册$routerVueRouter.install = function (_vue) {    Vue = _Vue;    // 工作2 挂载$router    // 为什么要应用混入的形式. 次要起因是vue.use代码在前,Router实例创立在后. 而install逻辑又须要应用到该实例    Vue.mixin({        beforeCreated(){            // 只有根组件领有router选项            if (this.$options.router) {                Vue.prototype.$router = this.$options.router;            }        }    })    // 工作2 实现两个全局组件router-link router-view    Vue.component('router-link',Link);    Vue.component('router-view',View);}export default VueRouter

实现router-link组件

<router-link to="/">点击</router-link>

Vue.component('router-link', {    props: {        to: {            type: String,            required: true        }    },    render (h) {        return h('a', {attrs: '#' + this.to}, this.$slots.default)    }})

实现router-view组件

Vue.component('router-view', {    render(h) {        // 临时不渲染任何内容        return h(null)    }})

监控url变动

定义响应式的current属性, 监听hashChange事件

class VueRouter {    constructor(options) {                // 定义响应式的属性current        const initial = window.location.hash.slice('#') || '/';        Vue.util.defineReactive(this, 'current', initial);        // 监听hash变动        window.addEventListener('hashchange', this.onHashChange.bind(this));                // 缓存path和route映射关系        this.routerMap = {};        this.$options.routes.forEach(route => {            this.routerMap[route.path] = route;        })    }    onHashChange(){        this.current = window.location.hash.splice(1);    }}// router-viewVue.component('router-view', {    render(h) {        const {routerMap , current} = this.$router;        const component = routerMap[current] ? routerMap[current].component : nu~~~~ll;        return h(component)    }})

残缺vue-router简略实现代码

let Vue;class VueRouter {    constructor(options) {        this.$options = options;        // 把current作为相应式数据         // 未来发送变动, router-view的render函数可能再次执行        this.current = '/';        const initial = window.location.hash.slice("#") || '/'        Vue.util.defineReactive(this, 'current', initial)        // 监听hash变动        window.addEventListener('hashchange', () => {            this.current = window.location.hash.slice(1);        })        // 缓存path和route映射关系        this.routerMap = {};        this.$options.routes.forEach(route => {            this.routerMap[route.path] = route        });        console.log(this.routerMap);    }}// _vue 是vue.use调用时传入的// 全局混入的目标: 提早上面逻辑到router创立结束并且 附加到选项上时才执行VueRouter.install = function(_Vue) {    Vue = _Vue;    // 1. 挂载$router属性    // 全局混入    Vue.mixin({        beforeCreate() {            // 此钩子在每个组件创立实例时都会调用            // 根实例才有该选项             if (this.$options.router) {                 Vue.prototype.$router = this.$options.router;              }        },    })    // 2. 注册实现两个自建 router-view, router-link    Vue.component('router-link', {        props: {            to: {                type: String,                required: true            }         },        render (h) {             // 应用插槽动静拿到组件蕴含的文案             return h(                 'a',                  {                     attrs:{                         href: '#'+this.to                     }                 },                  this.$slots.default)        },    });    Vue.component('router-view', {         render(h) {            // 获取以后路由对应的组件            const { routerMap, current} = this.$router;            const component = routerMap[current] ? routerMap[current].component: null;            return h(component)        },    });}export default VueRouter