最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 实现一个简易的vue-router

    正文概述 掘金(bluesky108)   2020-12-26   221

    前言

    最近在研究vue的源码,打算自己着手实现一些简单的功能,加深一下对框架的了解,于是准备实现一个简单的vue-router。

    准备工作

    先用vue-cli创建一个包含vue-router的demo,然后把项目引入的vue-router注释掉,改成自己写的js。

    hash模式和history模式的区别

    • 表现形式的区别
      • hash模式
      http:localhost/#/about
      • history模式
      http:localhost/about
    • 原理的区别
      • hash模式
      Vue Router默认使用的模式是hash模式,通过onhashchange事件监听url的变化。不需要后台人员进行配置
      • history模式
      使用的是H5的 History API,通过popstate事件监听url的变化。需要后台人员处理刷新页面的情况(找不到当前页面,在服务端应该除了静态资源外都返回单页应用的 index.html
      history.pushState({}, "", "bar.html") // 往浏览器添加历史记录
      history.replaceState({}, "", "bar.html") // 往浏览器修改当前的历史纪录
      history.go() // 跳转指定页面
      

    实现思路

    • 创建一个VueRouter类,有一个静态方法install,判断此插件是否加载过,只需加载一次。当Vue加载时,把传入的router对象挂载到Vue实例上(只执行一次)。
    • 在构造函数中,初始化,把传入的参数options放到自己的this上;创建一个routerMap对象,用来记录路由和组件的映射关系;利用Vue提供的 observable 方法创建一个响应式数据,记录当前的路由。
    • 创建initEvent事件,利用popstate事件监听history模式下路由的变化,利用hashchange事件监听hash模式下的变化。
    • 创建initRouterMap事件,循环传入的routes路由配置信息,把路由和组件的映射关系记录到routerMap对象中。
    • 创建initComponent事件,创建router-link和router-view两个组件。
    • 当路径改变时,通过routerMap找到对应的组件,渲染到router-view中。
    • 插件初始化时,执行initEvent、initRouterMap、initComponent事件。

    代码演示

    // my-Router.js
    
    let _Vue = null;
    
    class VueRouter {
      static install(Vue) {
        // 判断此插件是否安装过
        if(VueRouter.prototype.installed) {
          return
        }
        VueRouter.prototype.installed = true
        
        _Vue = Vue;
    
        // 把当前路由对象挂载到vue实例上
        _Vue.mixin({
          beforeCreate() { // 为什么在这里挂载,因为这里的this才是vue实例
            if(this.$options.router) {
              _Vue.prototype.$router = this.$options.router
            }
          }
        })
      }
    
      constructor(options) {
        // 传入的对象
        this.options = options;
        // 所有路由
        this.routerMap = {};
        // 当前路由
        this.data = _Vue.observable({
          current: "/",
        });
        this.init();
      }
    
      init() {
        //监听浏览器地址变化
        this.initEvent()
        // 把所有的路由添加到routerMap中
        this.initRouterMap();
        // 初始化全局的路由组件
        this.initComponent(_Vue);
      }
    
      initRouterMap() {
        for (let item of this.options.routes) {
          this.routerMap[item.path] = item.component;
        }
      }
    
      initEvent() {
        if(this.options.mode == 'history') {
          window.addEventListener('popstate', ()=>{
            this.data.current = window.location.pathname
          })
        }else {
          window.addEventListener('hashchange', ()=>{
            this.data.current = window.location.hash.substr(1)
          })
        }
      }
    
      initComponent(Vue) {
        let that = this;
    
        Vue.component("router-link", {
          props: {
            to: String,
          },
          render(h) {
            return h(
              "a",
              {
                attrs: {
                  href: this.to,
                },
                on: {
                  click: this.clickhander,
                },
              },
              [this.$slots.default]
            );
          },
          methods: {
            clickhander(e) {
              e.preventDefault();
              
              if(that.options.mode == 'history') {
                history.pushState({}, "", this.to);
              }else{
                history.pushState({}, "", '#' + this.to);
              }
              that.data.current = this.to;
            },
          },
        });
    
        Vue.component("router-view", {
          render(h) {
            let app = that.routerMap[that.data.current];
            return h(app);
          },
        });
      }
    }
    
    export default VueRouter;
    
    

    起源地下载网 » 实现一个简易的vue-router

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元