實現(xiàn)一個vueRouter

實現(xiàn)一個vue插件步驟

//1.定義一個類
class VuePlugin{
    
}
//2.實現(xiàn)類的靜態(tài)方法install Vue.use的時候會調用靜態(tài)方法,并傳入Vue
VuePlugin.install = function(Vue){
    
}
//3.暴露類
export default VuePlugin;

實現(xiàn)一個vueRouter

  • 實現(xiàn)組件router-link
  • 實現(xiàn)組件router-view
  • 實現(xiàn)插件MyRouter
// MyRouter.js
import Link from "@/components/KRouterLink";
import View from "@/components/KRouterView";
let Vue;
class MyRouter{
    constructor(options){
        this.$options = options;
        window.addEventListener("hashchange",this.onHashChange.bind(this,"hashchange"))
        window.addEventListener("load",this.onHashChange.bind(this,"load"))
        //matched存儲一個數(shù)組,里面放著要渲染組件相關的按照層級順序的route對象,比如[{path:"/about",component:About組件,children:[...省略]},{path:"/about/info",component:Info組件}]
        //注意:matched必須是響應式的,否則當matched改變的時候router-view的render函數(shù)不會重新觸發(fā)。
        Vue.util.defineReactive(this,"matched",[]);
    }
    onHashChange(eventType){
        this.matched = [];
        this.match()
    }
    match(routes){
        routes = routes || this.$options.routes;
        let current = location.hash.slice(1);
        for(const route of routes){
            if(current==="/" && route.path==="/"){
                this.matched.push(route);
                return;
            }
            //about/info
            if(current!=="/" && current.includes(route.path)){
                this.matched.push(route);
                if(route.children){
                    this.match(route.children);
                }
                return;
            }
        }
    }
}
MyRouter.install = function(_Vue){
    Vue = _Vue;
    //掛載$router到Vue的原型上
    //怎么獲取根實例的router配置呢,此時還沒有生成根實例呢。
    //利用全局混入
    Vue.mixins({
        beforeCreate(){
            if(this.$options.router){
                Vue.prototype.$router = this.$options.router;
            }
        }
    });
    //全局注冊組件
    Vue.component("router-link",Link)
    Vue.component("router-view",View)
}
export MyRouter;
//router-view組件
export default {
  render(h) {
    //標明當前組件是router-view
    this.$vnode.data.routerView = true;
    //記錄深度
    let depth = 0;
    let parent = this.$parent;
    while (parent) {
      if (
        parent.$vnode &&
        parent.$vnode.data &&
        parent.$vnode.data.routerView
      ) {
        depth++;
      }
      parent = parent.$parent;
    }
    //組件配置對象
    let comp = null;
    const route = this.$router.matched[depth];
    if (route) {
      comp = route.component;
    }
    return h(comp);
  },
};
//router-link組件
export default {
  //接收to路徑
  props: {
    to: {
        type:String,
        required:true
    },
  },
  render(h) {
    //createElement函數(shù),三個參數(shù):tag標簽、屬性、子元素集合
    // return h("a", { attrs: { href: "#" + this.to } }, [this.$slots.default]);

    //jsx方式
    return <a href={'#'+this.to}>{this.$slots.default}</a>
  },
};

大功告成可以測試了

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容