Vue-Routerの原理の紹介、独自のVue-Routerを手書き

事前知識

フロントエンドルーティングの2つのモード

  1. ハッシュモード
    URLの#の後ろのコンテンツがパスアドレスとして使用されます
    。HashChangeイベントをリッスンします。
    現在のルーティングアドレスに基づいて対応するコンポーネントを見つけ、再レンダリングします。
  2. 履歴モード
    history.pushState()メソッドを使用してアドレスバーを変更し、
    ポップステートイベントをリッスン
    し、現在のルーティングアドレスに基づいて対応するコンポーネントを見つけ、再レンダリングします。

手書きルーティングの準備

vue-routerなしで新しいvueプロジェクトを作成する

プロジェクトに新しいルーター関連ファイルを作成します

  1. 新しいルートフォルダを作成し、そのフォルダの下に新しいindex.jsを作成して、ルーティングルールを保存します
import Vue from 'vue'
import VueRouter from '../vuerouter'
//从我们自己的router中导入VueRouter
import Index from '../components/Index.vue'
Vue.use(VueRouter)

const routes = [
    {
    
    
        path:'/',
        name:'Index',
        component : Index
    },
    {
    
    
        path:'/about',
        name:'about',
        component: ()=> import('@/views/about.vue')
    },
    {
    
    
        path:'/home',
        name:'home',
        component: ()=> import('@/views/home.vue')
    },
]
const router = new VueRouter({
    
    
    mode:'history',
    base: process.env.BASE_URL,
    routes
})

export default router
  1. 新しいvuerouterフォルダーを作成し、フォルダーの下に新しいindex.jsを作成して、手書きのルーターコードを保存します。
    ここに画像の説明を挿入

  2. main.jsで作成したルーターを引用することを忘れないでください

import Vue from 'vue'
import App from './App.vue'
import router from './route'


Vue.config.productionTip = false

new Vue({
    
    
  router,
  render: h => h(App),
}).$mount('#app')

手書きのVue-Routerを開始します

まず、Vue-routerを手書きして何をすべきかを明確にする必要があります。次の図は、VueRouterに必要な属性とメソッドを詳細に記録したVue-routerのクラス図です。
ここに画像の説明を挿入

オプション:コンストラクターで渡されたオブジェクトを記録します(このオブジェクトにはルーティングルールがあります)
routeMap:ルーティングアドレスとコンポーネント間の対応を記録するために使用されるオブジェクトです。ルーティングルールは、将来の
データでrouteMapに解析されます。 :はオブジェクトです。現在のルーティングアドレスを記録するために使用される属性currentがあります。ここでは、データは応答オブジェクトを実装するために使用されます。

インストールメソッドの実装

クラス図の_から、インストールが静的メソッドであることがわかります。

let _Vue = null

export default class VueRouter {
    
    

    static install (Vue) {
    
    
        //判断当前插件是否被安装
        if(VueRouter.install.installed){
    
    
            return;
        }
        VueRouter.install.installed = true

        // 把vue构造函数记录到全局变量
        _Vue = Vue
        // 把创建vue实例的时候传入的router对象注入到Vue实例上
        //混入 mixed
        _Vue.mixin({
    
    
            beforeCreate() {
    
    
            if(this.$options.router)
                _Vue.prototype.$router = this.$options.router
            },
        })
    }

}

コンストラクターの実装

    constructor(options){
    
    
        this.options = options

        this.routerMap = {
    
    } // 用于存储解析的router对象
        this.data = _Vue.observable({
    
    
            current:'/'
        })
        // this.init()
    }

このようにして、クラス図の関連する属性が実現されます

CreateRouterMapメソッドの実装

このメソッドの機能は、コンストラクターに渡されたルーティングルールをキーと値のペアの形式に変換し、上記のrouteMapに格納することです。

//遍历所有的路由规则,解析路由规则变为键值对的形式,存储到routermap里
    createRouterMap(){
    
    
        this.options.routes.forEach(route =>{
    
    
            this.routerMap[route.path] = route.component
        })
    }

initComponentsメソッドの実装

    initComponents (Vue) {
    
    
        Vue.component('router-link',{
    
    
            props:{
    
    
                to:String
                //接收外部传入的to
            },
            // template:'<a :href="to"><slot></slot></a>'
            render (h) {
    
    
                return h('a',{
    
    
                    attrs:{
    
    
                        href:this.to
                    },
                    on:{
    
    
                        click:this.clickHandler
                    }
                },[this.$slots.default])
            },
            methods: {
    
    
                clickHandler(e){
    
    
                    history.pushState({
    
    },'',this.to)
                    this.$router.data.current = this.to
                    e.preventDefault();
                }
            },
        })
        const  _this = this
        Vue.component('router-view', {
    
    
            render(h) {
    
    
                const component = _this.routerMap[_this.data.current]
                return h(component)
            },
        })
    }

initEventメソッドの実装

initEvent(){
    
    
        window.addEventListener('popstate',()=>{
    
    
            this.data.current = window.location.pathname
        })
    }

この方法は、ブラウザで前後に移動するときにコンポーネントをロードしてレンダリングする方法です。

完全な手書きのルーティングコード

let _Vue = null

export default class VueRouter {
    
    

    static install (Vue) {
    
    
        //判断当前插件是否被安装
        if(VueRouter.install.installed){
    
    
            return;
        }
        VueRouter.install.installed = true

        // 把vue构造函数记录到全局变量
        _Vue = Vue
        // 把创建vue实例的时候传入的router对象注入到Vue实例上
        //混入 mixed
        _Vue.mixin({
    
    
            beforeCreate() {
    
    
            if(this.$options.router)
                _Vue.prototype.$router = this.$options.router
                // this.$options.router.init()
            },
        })
    }

    constructor(options){
    
    
        this.options = options

        this.routerMap = {
    
    } // 用于存储解析的router对象
        this.data = _Vue.observable({
    
    
            current:'/'
        })
         this.init()
    }
    init(){
    
    
        this.createRouterMap()
        this.initComponents(_Vue)
        this.initEvent()
    }
    //遍历所有的路由规则,解析路由规则变为键值对的形式,存储到routermap里
    createRouterMap(){
    
    
        this.options.routes.forEach(route =>{
    
    
            this.routerMap[route.path] = route.component
        })
    }
    initComponents (Vue) {
    
    
        Vue.component('router-link',{
    
    
            props:{
    
    
                to:String
            },
            // template:'<a :href="to"><slot></slot></a>'
            render (h) {
    
    
                return h('a',{
    
    
                    attrs:{
    
    
                        href:this.to
                    },
                    on:{
    
    
                        click:this.clickHandler
                    }
                },[this.$slots.default])
            },
            methods: {
    
    
                clickHandler(e){
    
    
                    history.pushState({
    
    },'',this.to)
                    this.$router.data.current = this.to
                    e.preventDefault();
                }
            },
        })
        const  _this = this
        Vue.component('router-view', {
    
    
            render(h) {
    
    
                const component = _this.routerMap[_this.data.current]
                return h(component)
            },
        })
    }
    initEvent(){
    
    
        window.addEventListener('popstate',()=>{
    
    
            this.data.current = window.location.pathname
        })
    }
}

参照:
Lagou Education

おすすめ

転載: blog.csdn.net/qq_43377853/article/details/113841827