乐趣区

关于vue-router:vuerouter

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 办法, 注册 $router
VueRouter.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-view
Vue.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
退出移动版