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;
  • 相关阅读:
    PHP获取指定的时间戳
    Thinkphp实现excel数据的导出
    ThinkPHP按月统计订单总金额
    PHP获取本月起始和终止时间戳
    ThinkPHP 判断一个更新操作是否成功
    js 通过浏览器直接打开应用程序(IOS,Android)并判断浏览器内核
    ThinkPHP 后台管理删除、编辑操作(通过数组传ID)
    PHP面向对象
    【转】Chrome调试鼠标悬停后出现的元素
    【重要】Selenium2+python自动化44-元素定位参数化(find_element)
  • 原文地址:https://www.cnblogs.com/xiaonian8/p/13825935.html
Copyright © 2011-2022 走看看