vue-router导航守卫进阶&源码实现

栏目: JavaScript · 发布时间: 5年前

内容简介:前端路由实现起来其实很简单,本质就是监听URL的变化,然后匹配路由规则,显示相应的页面,并且无须刷新。vue-router共有三种守卫,分别是全局守卫、路由独享守卫、组件内的守卫。效果等同于全局守卫ep:通过route设置document.title

前端路由实现起来其实很简单,本质就是监听URL的变化,然后匹配路由规则,显示相应的页面,并且无须刷新。vue-router共有三种守卫,分别是全局守卫、路由独享守卫、组件内的守卫。

导航守卫

  • 全局守卫

    你可以使用 router.beforeEach 注册一个全局前置守卫: ep:设置全局守卫,如果进入about页,没有登陆则重定向到login页

router.beforeEach((to,from,next) => {
      console.log(to.meta)
  // 判断是否登录
  if (to.path === '/about' && !window.isLogin) {
    next('/login?redirect='+to.path);
  } else {
    next();
  }
})
复制代码
  • 路由独享守卫
{
      path: "/about",
      name: "about",
      meta: {requireLogin:true},  // meta  取值就是to.meta
      beforeEnter(to,from,next) {
        // 判断是否登录  路由独享守卫
        if (!store.state.isLogin) {
          next('/login?redirect='+to.path);
        } else {
          next();
        }
      },
      component: () =>
        import(/* webpackChunkName: "about" */ "./views/About.vue")
}
复制代码

效果等同于全局守卫

  • 组件内的守卫
export default {
  beforeRouteEnter(to, from, next) {}
  beforeRouteUpdata(to, from, next) {}
  beforeRouteLeave(to, from, next) {}
}
复制代码

完整的导航解析流程

  1. 导航被触发。
  2. 在失活的组件里调用离开守卫。
  3. 调用全局的 beforeEach 守卫。
  4. 在重用的组件里调用 beforeRouteUpdate 守卫 (2.2+)。
  5. 在路由配置里调用 beforeEnter。
  6. 解析异步路由组件。
  7. 在被激活的组件里调用 beforeRouteEnter。
  8. 调用全局的 beforeResolve 守卫 (2.5+)。
  9. 导航被确认。
  10. 调用全局的 afterEach 钩子。
  11. 触发 DOM 更新。
  12. 用创建好的实例调用 beforeRouteEnter 守卫中传给 next 的回调函数。

meta路由元信息

ep:通过route设置document.title

{
    path: '/customer/new',
    name: 'NewCustomer',
    meta: {title: '新增客户'},
    component: () => import('@/Views/CustomerNew')
  },
  
  router.beforeEach(function (to, from, next) {
      if (to.meta && to.meta.title) {
        document.title = ((to.meta && to.meta.title))
      }
      next()
  })
复制代码

hash模式&&history模式

www.test.com/#/ 就是 Hash URL,当 # 后面的哈希值发生变化时,不会向服务器请求数据,可以通过 hashchange 事件来监听到 URL 的变化,从而进行跳转页面。

vue-router导航守卫进阶&源码实现

History 模式是 HTML5 新推出的功能,比之 Hash URL 更加美观

vue-router导航守卫进阶&源码实现

源码实现

应用页面

<router-link to="#/foo">foo</router-link> |
      <router-link to="#/bar">bar</router-link>
复制代码

router配置

const Foo = {
  render() {
    return <div>Foo</div>;
  }
};
const Bar = {
  render() {
    return <div>Bar</div>;
  }
};
export default new TRouter(Vue, {
  routes: [
    { 
      path: "/foo", 
      component: Foo
    },
    {
       path: "/bar",
       component: Bar
    }
  ]
});
复制代码

源码实现

import Vue from "vue";

class TRouter {
  constructor(Vue, options) {
    this.$options = options;
    this.routeMap = {}; // 全局的路由映射  key就是path(唯一的)
    this.app = new Vue({  // 对vue的强依赖
      data: {
        current: "#/"  // 当前路由
      }
    });
    this.init();
    this.createRouteMap(this.$options); 
    this.initComponent(Vue);
  }

  // 初始化 hashchange
  init() {
    // load事件在页面或某个资源加载成功时触发
    window.addEventListener("load", this.onHashChange.bind(this), false);
    // hashchange事件在 URL 的 hash 部分(即#号后面的部分,包括#号)发生变化时触发。
    window.addEventListener("hashchange", this.onHashChange.bind(this), false);
  }

  createRouteMap(options) {
    options.routes.forEach(item => {
      this.routeMap[item.path] = item.component;
    });
  }

  // 注册组件
  initComponent(Vue) {
    Vue.component("router-link", {  // 全局注册
      props: {
        to: String  // 去哪个地址
      },
      render: function (h) { // 传入函数  h 就是createElement
        // <a :href="to"><slot></slot></a>
        // 返回的是虚拟dom
        return h("a", { attrs: { href: this.to } }, this.$slots.default);
      }
    });

    const _this = this;  // 全局this
    Vue.component("router-view", {  // 占位符
      render(h) { // 根据当前路由发生变化  渲染当前组件所匹配的组件
        var component = _this.routeMap[_this.app.current];
        return h(component);
      }
    });
  }

  // 获取当前 hash 串
  getHash() {
    return window.location.hash.slice(1) || "/";
  }

  // 设置当前路径
  onHashChange() {  // 挂载的组件刷新
    this.app.current = this.getHash();  // 获取最新hish赋值
    console.log(this.app.current, 'this.app.current')
  }
}
复制代码

总结

vue-router对vue也是强依赖关系,简单的也可以理解为是对history的封装,本质上还是实现根据路由不同,返回不同内容。


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Is Parallel Programming Hard, And, If So, What Can You Do About

Is Parallel Programming Hard, And, If So, What Can You Do About

Paul E. McKenney

The purpose of this book is to help you understand how to program shared-memory parallel machines without risking your sanity.1 By describing the algorithms and designs that have worked well in the pa......一起来看看 《Is Parallel Programming Hard, And, If So, What Can You Do About 》 这本书的介绍吧!

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

RGB转16进制工具
RGB转16进制工具

RGB HEX 互转工具

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具