最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 默写Vue-Router

    正文概述 掘金(SandySY)   2021-01-15   399

    默写Vue-Router

    写在前面

    路由的源头

    说到底路由是根据不同的URL来展示不同的内容或页面,而路由的本质 就是建立起url和页面之间的映射关系。

    路由模式Hash和History

    Hash 模式使用了浏览器 URL 后缀中的#xxx部分来实现前端路由。默认情况下,URL后缀中的#xxx hash 部分是用来做网页的锚点功能的,现在前端路由看上了这个点,并对其加以利用。 比如这个 URL:http://www.abc.com/#/hello,hash 的值为 #/hello。 为什么会看上浏览器URL后缀中的 hash 部分呢?原因也简单:

    浏览器URL后缀中的 hash 改变了,不会触发请求,对服务器完全没有影响。它的改变不会重新加载浏览器页面。 更关键的一点是,因为hash发生变化的url都会被浏览器记录下来,从而你会发现浏览器的前进后退都可以用了,页面的状态与浏览器的URL就发生了挂钩。

    History 路由模式

    在 HTML5 之前,浏览器就已经有了 history 对象。但在早期的 history 中只能用于多页面的跳转,正如早期我们编写路由时,总会用到如下api控制页面跳转。

    history.go(-1);       // 后退一页
    history.go(2);        // 前进两页
    history.forward();     // 前进一页
    history.back();      // 后退一页
    //Html5 新增
    history.pushState();         // 添加新的状态到历史状态栈
    history.replaceState();      // 用新的状态代替当前状态
    history.state                // 返回当前状态对象
    

    默想是怎么使用的Vue-Router

    VueRouter 是作为插件的形式引入到 Vue 系统内部的。而将具体的 router 信息嵌入到每个 Vue 实例中,则是作为 Vue 的构造函数参数传入。

    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>今天进步了吗?</title>
        <script src="https://unpkg.com/vue/dist/vue.js"></script>
        <!-- <script src="https://unpkg.com/vue-router/dist/vue-router.js"></script> -->
        <script src="./vue-router-recode.js"></script>
      </head>
      <body>
        <div id="app">
          <h1>手写<strong>Vue-Router</strong></h1>
          <p>
            <!-- 使用 router-link 组件来导航. -->
            <!-- 通过传入 `to` 属性指定链接. -->
            <!-- <router-link> 默认会被渲染成一个 `<a>` 标签 -->
            <router-link to="/foo">Go to Foo</router-link>
            <router-link to="/bar">Go to Bar</router-link>
          </p>
          <!-- 路由出口 -->
          <!-- 路由匹配到的组件将渲染在这里 -->
          <router-view></router-view>
        </div>
        <script>
          // 0. 如果使用模块化机制编程,导入Vue和VueRouter,要调用 Vue.use(VueRouter)
    
          // 1. 定义 (路由) 组件。
          // 可以从其他文件 import 进来
          const Foo = { template: '<div>foo</div>' };
          const Bar = { template: '<div>bar</div>' };
    
          // 2. 定义路由
          // 每个路由应该映射一个组件。 其中"component" 可以是
          // 通过 Vue.extend() 创建的组件构造器,
          // 或者,只是一个组件配置对象。
          // 我们晚点再讨论嵌套路由。
          const routes = [
            { path: '/foo', component: Foo },
            { path: '/bar', component: Bar },
          ];
    
          // 3. 创建 router 实例,然后传 `routes` 配置
          // 你还可以传别的配置参数, 不过先这么简单着吧。
          const router = new VueRouter({
            routes, // (缩写) 相当于 routes: routes
          });
    
          // 4. 创建和挂载根实例。
          // 记得要通过 router 配置参数注入路由,
          // 从而让整个应用都有路由功能
          const vm = new Vue({
            router,
          }).$mount('#app');
    
          // 现在,应用已经启动了!
        </script>
      </body>
    </html>
    

    直接使用router-link和router-view这两个组件。它们是随着 Vue Router 一起引入的,作为全局组件使用。有了以上的想法,我们构建了这样的简单页面,接下来我们就手写一个vue-router-recode.js用于替换vue-router.js的职能。

    常规操作:wiki书写功能逻辑和实现思路

    简单版代码默写(快写hash,一个文件干完)

    对,干就完了!
    完整浏览了以上思路的,都不是难事儿,手敲速度慢的,建议多敲多写。Open with Live Server运行完美,直接上代码:

    let _Vue;
    class VueRouter {
      constructor({ routes }) {
        let routerMap = {};
        routes.forEach((route) => {
          let path = route.path;
          if (!routerMap[path]) {
            routerMap[path] = route;
          }
        });
        this.routerMap = routerMap;
        console.log(this.routerMap);
        //TODO
        this.current = {
          path: '',
          component: {
            template: `<div>default</div> `,
          },
        };
        this.linstener();
      }
      linstener() {
        window.addEventListener('load', () => {
          debugger;
          console.log('load');
          let hash = window.location.hash;
          if (!hash) {
            window.location.hash = '/';
          }
          let route = this.search(hash.slice(1));
          if (route) {
            this.current.path = route.path;
            this.current.component = route.component;
          }
        });
        window.addEventListener('hashchange', () => {
          debugger;
          console.log('hashchange');
          let hash = window.location.hash;
          let route = this.search(hash.slice(1));
          if (route) {
            this.current.path = route.path;
            this.current.component = route.component;
          }
        });
      }
      search(path) {
        if (this.routerMap[path]) {
          return this.routerMap[path];
        }
      }
    }
    
    VueRouter.install = function (Vue, options) {
      _Vue = Vue;
      _Vue.mixin({
        beforeCreate() {
          let vm = this;
          // console.log(vm);
          if (vm.$options.router) {
            vm._routerRoot = this;
            vm._router = vm.$options.router;
            //定义响应式数据
            _Vue.util.defineReactive(vm, '_route', vm._router.current);
          } else {
            vm._routerRoot = vm.$parent && vm.$parent._routerRoot;
          }
        },
      });
      _Vue.component('router-link', {
        props: {
          to: String,
        },
        render(c) {
          // h => createElement
          return c('a', { attrs: { href: '#' + this.to } }, this.$slots.default);
        },
      });
      _Vue.component('router-view', {
        render(c) {
          debugger;
          let component = this._routerRoot._route.component;
          return c(component);
        },
      });
    };
    
    if (typeof Vue !== 'undefined') {
      Vue.use(VueRouter);
    }
    

    总结

    本文主要为理解vueRouter源码提供一个最基础的框架和思路,如需要对vue生态有着较为深入的理解,如vue的插件机制,vue的双向绑定原理,后端路由和前端路由,hash模式相关api以及history模式相关api,更多相关的 Vue-Router 的细节,可以参考其官网。希望本文对你有用。

    为了方便阅读理解,本文代码已经上传Github
    文中如有错误,欢迎在评论区指正,如果有所帮助,欢迎点赞和关注


    起源地下载网 » 默写Vue-Router

    常见问题FAQ

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

    发表评论

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

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

    联系作者

    请选择支付方式

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