1. Hash模式(基于锚点,以及onhashchange事件)
实现原理:
- URL中 # 后面的内容作为路径地址
- 监听hashchange事件
-
2. History模式(基于HTML5中的History API)
1. 说明
history.pushState(), IE10以后才支持
- history.replaceState()```javascript // node.js服务器配置history模式 const path = require(“path”); const history = require(“connect-history-api-fallback”); const express = require(“express”); const app = express() // node.js中配置history模式 app.use(history()) app.use(express.static(path.join(__dirname, “../vue-router/dist”))) app.listen(9000, () => { console.log(“server is take on, port: 9000”) })
// nginx配置history模式 nginx.config文件中: location / { // 末尾添加 try_files $uri/ /index.html }
<a name="4Xcnb"></a>### 2. 实现原理- 通过history.pushState()方法改变地址栏- 监听popstate事件- 根据当前路由地址找到对应的组建重新渲染<a name="G44Ul"></a>### 3. 实现<a name="OsQEj"></a>#### 实现视图1. install静态方法, 用于对当前插件安装的处理1. 三个实例属性- options, 保存routers配置- routeMap, 保存路由的键值对- data, 保存当前路由3. createRouteMap实例方法, 遍历所有路由规则,以键值对的形式存储到routeMap中3. initComponents实例方法, 定义router-link组件和router-view组件3. initEvent实例方法, 用于监听popstate事件,当历史状态被激活的时候触发该事件,根据当前路由地址找到对应的组建重新渲染<a name="loqc4"></a>#### 实现代码```javascriptlet _Vue = nullexport default class VueRouter {// 注册vue-router插件的时候调用:Vue.use(VueRouter)static install (Vue) {// 1 判断当前插件是否已经安装if (VueRouter.install.installed) {return}VueRouter.install.installed = true// 2 把Vue构造函数记录到全局变量_Vue = Vue// 3 把创建Vue实例时候传入的router对象注入到Vue实例上_Vue.mixin({beforeCreate () {// Vue实例if (this.$options.router) {_Vue.prototype.$router = this.$options.routerthis.$options.router.init()}}})}constructor (options) {this.options = optionsthis.routeMap = {}this.data = _Vue.observable({current: '/'})}createRouteMap () {// 遍历所有路由规则,把路由规则解析成键值对形式存储到routeMap中this.options.routes.forEach(route => {this.routeMap[route.path] = route.component})}init () {this.createRouteMap()this.initComponents(_Vue)this.initEvent()}initComponents (Vue) {// router-link 组件Vue.component('router-link', {props: {to: String},// template: "<a :href='to'><slot></slot></a>"render (h) {return h('a',{attrs: {href: this.to},on: {click: this.clickHandler}},[this.$slots.default])},methods: {clickHandler (e) {// 通过history.pushState()改变地址栏history.pushState({}, '', this.to)// 根据当前路由地址找到对应的组建重新渲染this.$router.data.current = this.to// hash模式:// window.location.hash = this.to// 阻止超链接对默认行为e.preventDefault()}}})const self = this// router-view 组件Vue.component('router-view', {render (h) {const component = self.routeMap[self.data.current]return h(component)}})}// 监听popstate事件initEvent () {window.addEventListener('popstate', () => {this.data.current = window.location.pathname})// hash模式// window.addEventListener('hashchange', (e) => {// this.data.current = e.newURL.split('#')[1]// })}};
