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

    现在很多项目的前端都是用vue单页面实现的,而单页面中最重要的一个环节就是路由,今天来实现一个简易版本的vue-router。

    路由

    先来看下路由的工作流程

    后端路由

    1. 输入url
    2. 请求发送到服务器,服务器解析请求的路径
    3. 拿到相应数据-返回给前端

    前端路由

    1. 输入url
    2. js解析地址,找到对应地址的页面
    3. 执行页面生成的js和css
    4. 渲染页面

    了解了路由的工作流程之后,再来看下vue-router工作流程。

    1. url改变,触发监听事件
    2. 改变vue-router的current变量(new Router中的current变量)
    3. 监视current变量的监视者
    4. 获取新的组件,render新组件

    url改变,这就涉及了两种模式,hash和history。
    hash的特点

    • #后的就是hash的内容,只会给浏览器,不会给服务器
    • 可以通过location.hash获取
    • 可以通过onhashchange监听hash的改变

    history的特点

    • history即正常的路径
    • 可以通过location.pathname获取
    • 可以通过onpopstate见监听history变化

    看下router.js中的内容,实例化的时候会传mode和routers等其他参数

    import hello from './hello.vue';
    new Router({
        mode:'history',
        routers:[{
          path:'/',
          name: 'hello',
          component: hello
        }]
    })

    vue插件

    看下vue插件的用法
    1.插件都是用过Vue.use方法注册的,下面来看下一段代码。

    // 声明一个普通的对象test
    var test = {
        b: 1
    }
    // 写了一个定时器,2秒后改变了test的b属性的值
    setTimeout(function(){
        test.b = 111;
    },2000)
    // 声明了一个函数a
    function a(){
        console.log(1)
    }
    // 给a赋了一个install属性方法
    a.install = function(vue){
        // 对test对象的b属性进行双向绑定
        vue.util.definereactive(test,'b')
        // 全局混入
        vue.mixin({
          beforeCreate(){
             this.test = test;
          }
        })
    }
    // 注册插件a
    Vue.use(a);
    
    <div>{{test.b}}</div>

    运行这段代码,结果是会在页面上显示1,过了2秒会变成111,从这个demo中我们可以看出插件是可以将外面定义的变量实现双向绑定的。

    电脑刺绣绣花厂 http://www.szhdn.com 广州品牌设计公司https://www.houdianzi.com

    实现

    接下来实现了一个简易的路由,看下代码

    class HistoryRoute{
        constructor(){
          this.current = null;
        }
    }
    
    class vueRouter({
        constructor(opt){
           // 路由模式
           this.mode = opt.mode || 'hash';
           // 路由配置项
           this.routes = opt.routes || [];
           this.history = new HistoryRoute;
           // 将路由配置项由数组形式转成键值对
           this.routesMap = this.createMap(this.routes);
           // 初始化,获取、监听路由
           this.init()
        }
        init(){
           if(this.mode === 'hash'){
             location.hash ? "" : location.hash="/";
             window.addEventListener('load',()=>{
                this.history.current = location.hash.splice(1);
             });
             window.addEventListener('hashchange',()=>{
                 this.history.current = location.hash.splice(1)
             })
           }else {
             location.pathname ? "" : location.pathname="/";
             window.addEventListener('load',()=>{
                this.history.current = location.pathname;
             });
             window.addEventListener('popstate',()=>{
                 this.history.current = location.pathname
             })
           }
        }
        createMap(routes){
          return routes.reduce((memo,current)=>{
            memo[current.path] = current.component;
            return memo;
          },{})
        }
    })
    vueRouter.install = vue=>{
        vue.mixin({
          beforeCreate(){
            if(this.$options && this.$options.router){
              this._root = this;
              this._router = this.$options.router;
            }
            // 对current变量进行双向绑定
            vue.util.definereactive(this,'current', this._router.history)
          }else{
            //嵌套路由
            this._root = this.$parent._root;
          }
          // 定义this.$router的get方法,防止修改属性
          Object.defineProperty(this,'$router',{
             get(){
               return this._root._router;
             }
          })
        })
        // 注册一个router-view的组件,渲染路由组件
        vue.component('router-view',{
          render(h){
            let current = this._self._root._router.history.current;
            let routesMap = this._self._root._router.routesMap;
            return h(routesMap(current));
          }
        })
    }
    export default vueRouter;
  • 相关阅读:
    新一代MQ apache pulsar的架构与核心概念
    Flutter使用fluwx实现微信分享
    BZOJ3622 已经没有什么好害怕的了 动态规划 容斥原理 组合数学
    NOIP2016提高组Day1T2 天天爱跑步 树链剖分 LCA 倍增 差分
    Codeforces 555C Case of Chocolate 其他
    NOIP2017提高组Day2T3 列队 洛谷P3960 线段树
    NOIP2017提高组Day2T2 宝藏 洛谷P3959 状压dp
    NOIP2017提高组Day1T3 逛公园 洛谷P3953 Tarjan 强连通缩点 SPFA 动态规划 最短路 拓扑序
    Codeforces 873F Forbidden Indices 字符串 SAM/(SA+单调栈)
    Codeforces 873E Awards For Contestants ST表
  • 原文地址:https://www.cnblogs.com/xiaonian8/p/13825935.html
Copyright © 2011-2022 走看看