内容简介:在挂载router-view组件时,会生成一个watcher, router-view的render函数中又触发了_route的getter方法,那么此watcher就被收集到_route的Dep中了。在_route的setter触发时,自然执行了这个watcher, 组件重新render。
问题
1. 为什么url变更时,router-view组件就能渲染出在routes中定义的与当前path匹配的组件?
-
root vue实例上定义了一个响应式属性
Vue.util.defineReactive(this, '_route', this._router.history.current) -
url变更时,会匹配到最新的route,并且会设置
this._routerRoot._route, 触发setter -
router-view组件的render函数中有使用到
parent.$route, 也就是间接的触发了this._routerRoot._route的getter。 -
则
this._routerRoot._route的setter触发时即会触发router-view的渲染watcher, 再次渲染, 并且此时拿到的路由组件也是最新的。
本质上利用了vue的响应式属性,在route属性变更和router-view视图渲染之间建立关系。
route变更 => render重新渲染
2. router-view render中使用到 parent.$route
为什么就会被 this._routerRoot._route
收集watcher
在挂载router-view组件时,会生成一个watcher, router-view的render函数中又触发了_route的getter方法,那么此watcher就被收集到_route的Dep中了。
在_route的setter触发时,自然执行了这个watcher, 组件重新render。
在 vue的仓库中 vue/src/core/instance/lifecycle.js
中 mountComponent
方法中,能看到挂载组件时是会生成一个 watcher
的:
export function mountComponent(
vm: Component,
el: ?Element,
hydrating?: boolean
) {
...
let updateComponent
updateComponent = () => {
vm._update(vm._render(), hydrating)
}
new Watcher(vm, updateComponent, noop, {
before() {
...
}
})
...
return vm
}
3. this.$router, this.$route是怎么挂载每个vue组件上的?
Object.defineProperty(Vue.prototype, '$router', {
get () { return this._routerRoot._router }
})
Object.defineProperty(Vue.prototype, '$route', {
get () { return this._routerRoot._route }
})
4.替换routes的写法(这样写为什么有用)
// 替换现有router的routes
router.matcher = new VueRouter({
routes: newRoutes
}).matcher
router.matcher是比较核心的一个属性。对外提供两个方法match(负责route匹配), addRoutes(动态添加路由)。
具体原因:在做路径切换 transitionTo
方法中,首先就会使用 const route = this.router.match(location, this.current)
来匹配route, 其实内部会使用matcher来做匹配。修改了watcher即新的routes生效。
对router.matcher属性做修改,即新的routes就会替换老的routes, 其实就是 replaceRoutes()
的含义。
export type Matcher = {
match: (raw: RawLocation, current?: Route, redirectedFrom?: Location) => Route;
addRoutes: (routes: Array<RouteConfig>) => void;
};
5. router-view是什么
<router-view> 组件是一个functional 组件,渲染路径匹配到的视图组件。<router-view> 渲染的组件还可以内嵌自己的 <router-view>,根据嵌套路径,渲染嵌套组件。
<transition>
<keep-alive>
<router-view></router-view>
</keep-alive>
</transition>
工作原理简要流程图
hashchange --> match route --> set vm._route --> <router-view> render() --> render matched component
主要流程
-
初始化
- 实例化Router, options作为属性,根据mode生成HTML5History实例,或HashHistory实例
- 数据劫持,this.router.route =》 this.history.current
- 数据劫持,this.history.current.route变化时,自动执行render。
- 立即执行一次路由跳转(渲染路由组件)
-
路由监听
- HashHistory监听hashChange事件,HTML5History监听popstate事件
-
路由变化处理
-
两种方式触发路由变化
- a标签href方法(url先变化,会触发两个history监听的hashChange或popstate事件,然后进入路由变化处理)
- 调用router的push, replace, go方法(先进入路由变化处理,然后修改url)
-
路由变化具体处理过程
- history.transitionTo(根据path匹配到相应的route, 然后调度执行hooks, 然后更新this.current属性,触发视图更新)
- history.confirmTransition(调度执行上一个route和下一个route的相关生命周期hooks)
-
-
router的辅助API
- push(先进行路由变化处理,在更新url,使用history.pushState)
- replace() 和push处理方式一致, 只是更新url使用history.replaceState
- go 使用history.go方法
参考链接
https://cnodejs.org/topic/58d...
https://zhuanlan.zhihu.com/p/...
https://ustbhuangyi.github.io... 【这个比较详细,但是废话太多,看不清重点】
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- AOP概述及实现原理
- MySQL 主从基于 GTID 复制原理概述
- MySQL 主从基于position复制原理概述
- Qt Inside 之信号和槽原理概述
- 【译】JavaScript的工作原理:引擎,运行时和调用堆栈的概述
- 服务端指南 服务端概述 | 微服务架构概述
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Domain-Driven Design
Eric Evans / Addison-Wesley Professional / 2003-8-30 / USD 74.99
"Eric Evans has written a fantastic book on how you can make the design of your software match your mental model of the problem domain you are addressing. "His book is very compatible with XP. It is n......一起来看看 《Domain-Driven Design》 这本书的介绍吧!