VUE-Router
VUE-Router 主要和Vue搭配创建单页应用使用的,用vuer-router要将components映射到routes,并告知在哪里渲染组件
动态路由传参
const routes = [
{
name: 'detail',
// 路径中携带参数
path: '/detail/:id',
component: detail
}
]
// detail 组件中接收路由参数
$route.params.id
const routes = [
{
name: 'detail',
// 路径中携带参数
path: '/detail/:id',
component: detail,
props: true //设置为true,可在组件中props接收
}
]
// detail 组件中接收路由参数
const detail = {
props: ['id'],
template: '<div>Detail ID: {{ id }}</div>'
}
vue-router 核心
// 注册插件
// Vue.use() 内部调用传入对象的 install 方法
Vue.use(VueRouter)
// 创建路由对象
const router = new VueRouter({
routes: [
{ name: 'home', path: '/', component: homeComponent }
]
})
// 创建 Vue 实例,注册 router 对象
new Vue({
router,
render: h => h(App)
}).$mount('#app')
hash模式实现
Vue Router 默认使用的是 hash 模式,使用 hash 来模拟一个完整的 URL,通过
onhashchange 监听路径的变化
-
1-创建 LVueRouter 插件
export default class VueRouter { static install(Vue) { // 如果插件已经安装直接返回 if (VueRouter.install.installed && _Vue === Vue) return VueRouter.install.installed = true _Vue = Vue Vue.mixin({ beforeCreate() { // 判断 router 对象是否已经挂载了 Vue 实例上 if (this.$options.router) { // 把 router 对象注入到 Vue 实例上 _Vue.prototype.$router = this.$options.router } }, }) } }
-
2-实现 VueRouter 类 - 构造函数
constructor(options) { this.options = options this.routerMap = {} //记录组件和路由映射数据 this.data = _Vue.observable({ current: '/', //响应式对象,当前路径 }) }
-
3- 实现 LVueRouter 类 - initRouteMap()
initRouteMap() { // routes => [{ name: '', path: '', component: }] // 遍历所有的路由信息,记录路径和组件的映射 this.options.routes.forEach((route) => { // 记录路径和组件的映射关系 this.routeMap[route.path] = route.component }) }
-
4- 实现 LVueRouter 类 - 注册事件
initEvents () { // 当路径变化之后,重新获取当前路径并记录到 current window.addEventListener('hashchange', this.onHashChange.bind(this)) window.addEventListener('load', this.onHashChange.bind(this)) } onHashChange () { this.app.current = window.location.hash.substr(1) || '/' }
-
5- 实现 LVueRouter 类 - router-link 和 router-view 组件
initComponents() { _Vue.component('RouterLink', { props: { to: String, }, // 需要带编译器版本的 Vue.js // template: "<a :href='\"#\" + to'><slot></slot></a>" // 使用运行时版本的 Vue.js render(h) { return h('a', { attrs: { href: '#' + this.to, }, }, [this.$slots.default]) } }) const self = this _Vue.component('RouterView', { render (h) { // 根据当前路径找到对应的组件,注意 this 的问题 const component = self.routeMap[self.app.current] return h(component) } }) }
-
注意:
-
vue-cli 创建的项目默认使用的是运行时版本的 Vue.js,无编译器
-
如果想切换成带编译器版本的 Vue.js,需要修改 vue-cli 配置
-
项目根目录创建 vue.config.js 文件,添加 runtimeCompiler
module.exports = { runtimeCompiler: true }
-
-
-
6- 实现 LVueRouter 类 - init()
init () { this.initRouteMap() this.initEvents() this.initComponents() } // 插件的 install() 方法中调用 init() 初始化 if (this.$options.router) { _Vue.prototype.$router = this.$options.router // 初始化插件的时候,调用 init this.$options.router.init() }
history模式实现
https://developer.mozilla.org/zh-CN/docs/Web/API/History_API
实现思路
- 创建 LVueRouter 插件,静态方法 install
- 判断插件是否已经被加载
- 当 Vue 加载的时候把传入的 router 对象挂载到 Vue 实例上(注意:只执行一次)
- 创建 LVueRouter 类
- 初始化,options、routeMap、app(简化操作,创建 Vue 实例作为响应式数据记录当前路
径) - initRouteMap() 遍历所有路由信息,把组件和路由的映射记录到 routeMap 对象中
- 注册 popstate 事件,当路由地址发生变化,重新记录当前的路径
- 创建 router-link 和 router-view 组件
- 当路径改变的时候通过当前路径在 routerMap 对象中找到对应的组件,渲染 router-view
- 初始化,options、routeMap、app(简化操作,创建 Vue 实例作为响应式数据记录当前路
代码实现
-
1-; 2-; 3-;同hash
-
4-实现 LVueRouter 类 - 注册事件
initEvent(){ window.addEventListener("popstate",()=>{ this.data.current = window.location.pathname }) }