vue2.0 router及简易实现
· 分享镜#vue
分类
hash
- URL中 # 后面的内容作为路径地址
- hash的模式是基于锚点,以及onhashchange 事件
- 根据当前路由地址找到对应组件重新渲染
history
- history 模式是基于html5中的history api
- history.pushState() ie10 以后才支持
- history.replaceState()
- 通过history.pushState()方法改变地址栏
- 监听popstate 事件
- 根据当前路由地址找到对应组件重新渲染
服务端配置history
express配置
const path = require('path')
const history = require('connect-history-api-fallback')
const express = require('express')
const app = express()
// 注册处理history 模式的中间件
app.use(history())
// 处理金泰资源的中间件,网站根目录 ../web
app.use(express.static(path.join(__dirname, '../web')))
app.listen(3000, ()=>{
console.log('服务器开启,端口:3000')
})
nginx 配置
server{
...
location / {
root html;
index index.html index.html;
try_files $uri $uri/ index.html;
}
...
}
history 实现
简易版说明
- 只支持routes 参数
- 只支持router-link 和router-view 组件
- 不支持push replace 等功能
实现
- 写一个VueRouter class类
- 提供静态 install 方法
- 接受一个Vue参数
- 判断当前 router是否已经被安装
- 把Vue的构造函数记录在全局
- 把创建Vue的实例传入的router对象 注入到Vue实例中
- 使用mixin的方式注入
- 在beforeCreate 钩子中注入
- 提供构造函数constructor 处理参数和初始化
- 初始化参数options
- 将routes存放在routeMap中
- 记录当前的current, 并设置为响应式
- 通过Vue.observable来实现
- 初始化组件信息
- 处理组件 router-link 和router-view 注册为全局组件
- router-link
- 处理router-link 组件 接受一个参数to
- router-link即为a标签,to即为href的参数
- 拦截a标签的onClick事件,将history中pushState 记录跳转记录
- 设置当前的current为to的值
- router-view
- 处理router-view 组件
- router-view组件,用于展示当前路由的对应的component内容
- 获取当前的current,通过routerMap获取对应的component
- render 函数中return component vnode
- 由于current 是响应式的,router-view中的render 会实时 获取最新的component来渲染
- router-link
- 处理监听事件
- 由于router-link中 点击的时候,在history中添加了state,浏览器会根据hsitory的state自动处理前进和后退箭头
- 箭头浏览器的前进后退事件及popstate,重新设置对应的current
- 触发了router-view中component的渲染
let _Vue = null;
export default class 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() {
if (this.$options.router) {
_Vue.prototype.$router = this.$options.router
}
},
})
}
constructor(options) {
// 初始化参数
this.options = options;
// 将routes 存放在routeMap中
this.routeMap = {}
// 记录当前的current,并设置为响应式
this.data = _Vue.observable({
current: '/'
})
this.init()
}
init() {
this.createRouteMap()
this.initComponent(_Vue)
this.initEvent()
}
// 创建routeMap的数据
createRouteMap() {
this.options.routes.forEach(item => {
this.routeMap[item.path] = item.component
})
}
// 处理组件
initComponent(Vue) {
Vue.component('router-link', {
props: {
to: String
},
render(h) {
console.log('this.$slots.default', this.$slots.default)
return h('a', {
attrs: {
href: this.to
},
on: {
click: this.clickhander
}
}, [this.$slots.default])
},
methods: {
clickhander(e) {
e.preventDefault();
history.pushState({}, '', this.to)
this.$router.data.current = this.to
}
}
})
Vue.component("router-view", {
render: (h) => {
const cm = this.routeMap[this.data.current]
return h(cm)
}
})
}
// 监听事件 替换的current
initEvent() {
window.addEventListener('popstate', () => {
this.data.current = window.location.pathname
})
}
}
hash实现
简易版说明
- 只支持routes参数
- 只支持router-link和router-view组件
- 不支持push replace等功能
实现
- 和history实现整理类似, 可以继续使用history的模式
- 或者通过hashchange监听路由变化,设置current的值
window.addEventListener('hashchange', () => {
this.data.current = window.location.hash
})
let _Vue = null;
export default class 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() {
if (this.$options.router) {
_Vue.prototype.$router = this.$options.router
}
},
})
}
constructor(options) {
// 初始化参数
this.options = options;
// 将routes 存放在routeMap中
this.routeMap = {}
// 记录当前的current,并设置为响应式
this.data = _Vue.observable({
current: '#/'
})
this.init()
}
init() {
this.createRouteMap()
this.initComponent(_Vue)
this.initEvent()
}
// 创建routeMap的数据
createRouteMap() {
this.options.routes.forEach(item => {
this.routeMap[item.path] = item.component
})
}
// 处理组件
initComponent(Vue) {
Vue.component('router-link', {
props: {
to: String
},
render(h) {
return h('a', {
attrs: {
href: this.to
},
on: {
click: this.clickhander
}
}, [this.$slots.default])
},
methods: {
clickhander() {
this.$router.data.current = this.to
}
}
})
Vue.component("router-view", {
render: (h) => {
const cm = this.routeMap[this.data.current]
return h(cm)
}
})
}
// 监听事件 替换的current
initEvent() {
// window.addEventListener('popstate', () => {
// this.data.current = window.location.hash
// })
window.addEventListener('hashchange', () => {
console.log(window.location)
this.data.current = window.location.hash
})
}
}
评论(1)
登录后参与评论。
- 游游客
解决

