温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

Vue Router怎么实现

发布时间:2021-05-18 14:47:56 来源:亿速云 阅读:206 作者:小新 栏目:web开发

这篇文章将为大家详细讲解有关Vue Router怎么实现,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。

为什么需要前端路由

在前后端分离的现在,大部分应用的展示方式都变成了 SPA(单页面应用 Single Page Application)的模式。为什么会选择 SPA 呢?原因在于:

  • 用户的所有操作都在同一个页面下进行,不进行页面的跳转。用户体验好。

  • 对比多页面,单页面不需要多次向服务器请求加载页面(只请求一次.html文件),只需要向服务器请求数据(多亏了 ajax)。因此,浏览器不需要渲染整个页面。用户体验好。

归根结底,还是因为 SPA 能够提供更好的用户体验。

为了更好地实现 SPA,前端路由是必不可少的。假设一个场景:用户在 SPA 页面的某个状态下,点击了强制刷新按钮。如果没有前端路由记住当前状态,那么用户点击该按钮之后,就会返回到最开始的页面状态。这不是用户想要的。

当然,需要前端路由另一个点在于:我们可以更好地进行 SPA 页面的管理。通过将组件与路由发生配对关联,依据路由的层级关系,可为 SPA 内部的组件划分与管理提供一个依据参考。

Hash 路由模式 与 History 路由模式

这是两种常见的前端路由模式。

Hash 路由模式

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

为什么会看上浏览器URL后缀中的 hash 部分呢?原因也简单:

  • 浏览器URL后缀中的 hash 改变了,不会触发请求,对服务器完全没有影响。它的改变不会重新加载浏览器页面。

  • 更关键的一点是,因为hash发生变化的url都会被浏览器记录下来,从而你会发现浏览器的前进后退都可以用了,页面的状态与浏览器的URL就发生了挂钩。

hash模式背后的原理是onhashchange事件,可以在window对象上监听这个事件。

History 路由模式

随着 HTML5 中 history api 的到来,前端路由开始进化了。hashchange 只能改变 # 后面的代码片段,history api (pushState、replaceState、go、back、forward) 则给了前端完全的自由。简单讲,它的功能更为强大了:分为两大部分,切换和修改。

路由切换

参考MDN,切换历史状态包括 back、forward、go 三个方法,对应浏览器的前进,后退,跳转操作。

history.go(-2);//后退两次 history.go(2);//前进两次 history.back(); //后退 hsitory.forward(); //前进

路由修改

修改历史状态包括了pushState,replaceState两个方法:

/**  ** 参数含义  ** state: 需要保存的数据,这个数据在触发popstate事件时,可以在event.state里获取  ** title:标题,基本没用,一般传 null  ** url:设定新的历史记录的 url  */  window.history.pushState(state, title, url)  //假设当前的url是:https://www.abc.com/a/ //例子1 history.pushState(null, null, './cc/') //此时的url为https://www.abc.com/a/cc/ //例子2 history.pushState(null, null, '/bb/') //此时的url为https://www.abc.com/bb/

同样的,history 模式可以监听到对应的事件:

window.addEventListener("popstate", function() { // 监听浏览器前进后退事件,pushState 与 replaceState 方法不会触发  });

History 模式的注意点

和 Hash 模式相比,History 模式存在着更多的选择。但是也有一些自身的注意点:在用户点击强制刷新的时候,History 模式会向服务器发送请求。

为了解决这个问题,需要服务器做对应的处理。服务器可以针对不同的URL进行处理,当然,也可以简单处理:只要是未匹配到的URL请求,一律返回同一个 index.html 页面。

Vue Router 做了什么?

Vue Router 作为 Vue 生态系统中非常重要的一个成员,它实现了 Vue 应用的路由管理。可以说,Vue Router 是专门为 Vue 量身定制的路由管理器,功能点非常多。它的内部实现是与 Vue 自身是有强耦合关系的(Vue Router 内部利用了 Vue 的数据响应式)。
我们来看一个典型的 Vue Router 配置:

import Vue from "vue"; import App from "./vue/App.vue"; import VueRouter from 'vue-router'; //以插件的形式,使用VueRouter Vue.use(VueRouter); //路由配置信息,可以从外部文件引入,在此直接写是为了方便演示 const Foo = { template: '<div>foo</div>' } const Bar = { template: '<div>bar</div>' } const routes = [  { path: '/', component: Foo },  { path: '/bar', component: Bar } ] //初始化并与 Vue 实例关联 const router = new VueRouter({routes}); new Vue({  router,  render: h => h(App), }).$mount("#root");

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

同时来看看如何使用它:

//routerExample.vue <template>   <div>     <h2 @click="goBack">App Test</h2>     <router-link to="/">foo</router-link>     <router-link to="/bar">bar</router-link>     <router-view></router-view>   </div> </template> <script> export default {  methods: {   goBack() {    console.log(this.$router);     window.history.length > 1 ? this.$router.go(-1) : this.$router.push('/')   }  } } </script> <style lang="less" scoped> </style>

上面的代码中,我们可以直接使用router-link和router-view这两个组件。它们是随着 Vue Router 一起引入的,作为全局组件使用。

这就是一个最简单的 Vue Router 的使用方式。我们下面就来看看,该如何自己实现上面的简单功能,做一个自己的 Vue Router。

一个简单的 Vue Router 实现

看了上面的这个过程,最简单的 Vue Router 应该包括以下实现步骤:

实现 Vue 规定的插件的写法,将我们自己的Vue Router 作为插件引入 Vue 系统中。

  • router功能一:解析传入的routes选项,以备调用

  • router功能二:监控URL变化(两种路由方式:history、hash)

实现两个全局组件:router-link和router-view

看看自定义的 Vue Router 的实现:

//FVueRouter.js  let Vue; //保存 Vue 构造函数的引用,与 Vue 深度绑定  class FVueRouter {   constructor(options){     this.$options = options;     //保存路由的路径与路由组件的对应关系     this.routerMap = {};     //当前的URL必须是响应式的,使用一个新的 Vue 实例来实现响应式功能     this.app = new Vue({       data: {current : "/"}     })   }   init(){     //监听路由事件     this.bindEvents();     //解析传入的routes     this.createRouterMap();     //全局组件的声明     this.initComponent();   }   bindEvents(){     window.addEventListener('hashchange', this.onHashChange.bind(this));   }   onHashChange(){     this.app.current = window.location.hash.slice(1) || '/';   }   createRouterMap(){     this.$options.routes.forEach(route => {       this.routerMap[route.path] = route;     })   }   initComponent() {     // 形式:<router-link to="/"> 转换目标=> <a href="#/" rel="external nofollow" >xxx</a>     Vue.component("router-link", {      props: {       to: String,      },      render(h) {       // h(tag, data, children)       return h('a', {         attrs: {href: '#' + this.to}       }, [this.$slots.default])      },     });     // 获取path对应的Component将它渲染出来     Vue.component("router-view", {       render: (h) => {         //此处的this 能够正确指向 FVouter内部,是因为箭头函数         const Component = this.routerMap[this.app.current].component;         return h(Component)       }     })    }  }  // 所有的插件都需要实现install 方法,传入参数是Vue的构造函数  FVueRouter.install = function(_Vue){   //将Vue的构造函数保存起来   Vue = _Vue;   //实现一个混入操作的原因,插件的install阶段非常早,此时并没有Vue实例   //因此,使用mixin,延迟对应操作到Vue实例构建的过程中来执行。   Vue.mixin({     beforeCreate(){       //获取到Router的实例,并将其挂载在原型上       if(this.$options.router){         //根组件beforeCreate时只执行一次         Vue.prototype.$router = this.$options.router;         this.init();       }     }   })  } export default FVueRouter;

这里是最为简单的一种实现。有几个值得注意的点:

  • 如上代码,将最基本的一个Vue Router 的代码架子搭建起来了,能够运行。但细微处依然需要酌情考虑。

  • 关于插件的写法:自定义插件内部必须实现一个 install 方法,传入参数是Vue的构造函数。

  • 使用了一个新的Vue 实例,将 URL 的 hash 变量进行数据响应化处理。

  • 关于渲染函数 render 的参数 h,它实际上是 createElement 函数。具体用法值得深究。代码中使用的是最为简单的处理方式。

vue是什么

Vue是一套用于构建用户界面的渐进式JavaScript框架,Vue与其它大型框架的区别是,使用Vue可以自底向上逐层应用,其核心库只关注视图层,方便与第三方库和项目整合,且使用Vue可以采用单文件组件和Vue生态系统支持的库开发复杂的单页应用。

关于“Vue Router怎么实现”这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,使各位可以学到更多知识,如果觉得文章不错,请把它分享出去让更多的人看到。

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI