zoukankan      html  css  js  c++  java
  • 简易vue-router 源码实现

    main.js中

    import Vue from "vue";
    import App from "./App.vue";
    import router from './krouter'
    
    Vue.config.productionTip = false;
    
    Vue.prototype.$bus = new Vue();
    
    new Vue({
      router,
      render: h => h(App)
    }).$mount("#app");

    kvue-router.js   文件   --->  插件实现

    let Vue;
    
    class VueRouter {
        constructor(options) {
            this.$options = options
    
            // 创建一个路由的path和route映射
            this.routeMap = {}
    
            // 将来当前路径current需要响应式
            // 利用Vue的响应式原理可以做到这一点
            this.app = new Vue({
                data: {
                    current: '/'
                }
            })
        }
        init(){
            // 绑定浏览器事件
            this.bindEvents()
    
            // 解析路由配置
            this.createRouteMap(this.$options)
    
            // 创建router-link 和 router-view
            this.initComponent()
        }
        bindEvents() {
            window.addEventListener('hashchange', this.onHashChange.bind(this))
            window.addEventListener('load', this.onHashChange.bind(this))
        }
        onHashChange() {
            // http://localhost/#/home   slice(1)可以把#去掉,拿后面的部分
            this.app.current = window.location.hash.slice(1) || '/'
        }
        createRouteMap(options){
            options.routes.forEach(item => {
                // ['/home']: {path: '/home', component: Home}
                this.routeMap[item.path] = item
            })
        }
        initComponent(){
            // 声明两个全局组件
            Vue.component('router-link', {
                props: {
                    to: String
                },
                render(h) {
                    // 目标是:<a :href="to">xxx</a>
                    return h('a', {attrs: {href: '#'+this.to}}, this.$slots.default)
    
                    // jsx写法
                    // return <a href={this.to}>{this.$slots.default}</a>
                }
            })
    
            // hash -> current -> render
            Vue.component('router-view', {
                // 箭头函数能保留this指向,这里指向VueRouter实例
                render: (h) => {
                    const Comp = this.routeMap[this.app.current].component
                    return h(Comp)
                }
            })
        }
    }
    
    // 把VueRouter变为插件
    VueRouter.install = function(_Vue) {
        Vue = _Vue // 这里保存,上面使用
    
        // 混入任务
        Vue.mixin({ // 混入就是扩展Vue
            beforeCreate() {
                // 这里的代码将来会再外面初始化的时候被调用
                // 这样外面就实现了Vue扩展
                // 这里的this就是Vue实例
                // 但是这里会在所有组件的创建过程中都执行,所以这里不健壮
                // Vue.prototype.$router = this.$options.router   
    
                // 这里只希望根组件执行一次
                if(this.$options.router){
                    Vue.prototype.$router = this.$options.router
                    // 路由进行初始化
                    this.$options.router.init()
                }
            }
        })
    }
    
    export default VueRouter

    krouter.js  --->  相当于router.js

    import Vue from 'vue'
    import VueRouter from './kvue-router'
    import About from './views/About.vue'
    import Home from './views/Home.vue'
    
    // 插件注册
    Vue.use(VueRouter)
    
    export default new VueRouter({
        routes: [
            {path: "/", component: Home},
            {path: "/about", component: About}
        ]
    })
  • 相关阅读:
    Jquery:强大的选择器<一>
    要经营我的园子了!!!
    Json在Struts中的转换与传递
    MyEclipse快捷键大全
    Pyqt在QListWidget中添加右键菜单
    swift中Double转String
    Spring MVC 关于分页的简单实现
    Spring MVC 通过@Value注解读取.properties配置内容
    SQL 查询语句(备份)
    Idea使用说明
  • 原文地址:https://www.cnblogs.com/haishen/p/11309288.html
Copyright © 2011-2022 走看看