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>
#### 实现代码
```javascript
let _Vue = null
export 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.router
this.$options.router.init()
}
}
})
}
constructor (options) {
this.options = options
this.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]
// })
}
};