使用过dva
这款轻量框架的朋友应该对dynamic.js
这个文件不陌生,他负责注册动态加载的model
、渲染动态加载的component
。
先聊一下自己看代码最初没有理解的地方^_^,dynamic()
入口方法:
这句代码咋看只是用了一个解构重命名的技巧,但是阅读起来就会产生疑惑。resolveModels
为什么要这么命名呢,好端端的 models
不好么。其实这涉及到了大家对传入dynamic
中的参数的理解。
promise
的执行函数,因为执行后会得到一个 promise
的结果,所以起名为 resolveXXX
。 下面这段操作,开始我是一头雾水。
Promise.all
, ret.slice(0, len)
, resolve(xxx)
拆开来都能看懂,为什么拼起来就看不明白了呢。 让我们逐步来分析一下
-
[...models, component]
是什么?答:动态加载
models
、component
的promise
-
ret
是什么?答:所有
promise
执行完后的返回值组合而成的数组 -
为什么要做
models
的length
判断?答:方便没有
models
时,直接resolve(组件)
-
ret.slice(0, len)
是什么?答:所有
models
的返回结果组成的数组 -
resolve(XXX)
到底resolve
了什么?答:
resolve
了一个组件
到此终于可以搞清楚这段代码的作用就是将加载 models
、component
的 promise
执行结果的数组中的 models
拿去注册,components resolve
到下个环节。
作为一个有求知欲的小伙伴(其实可能是个杠精),我对于源码的探索并没有止步,我发现了一个令我疑惑不解的事情this.mounted
。
-
为什么
this.load()
要在contructor()
中执行,这个徒增了this.mounted
变量,如果在componentDidMount()
中去执行不应该更好么。 -
如果
this.state.AsyncComponent = AsyncComponent
, 在render
之后,在componentDidMount
之前执行,会不会导致组件无法正常展示。
于是我请教了我们的垚哥哥,垚哥哥给出了非常让我信服的解释。
- 因为如果组件很快从
componentDidMount
状态变为componentWillUnmount
,比如用户切换功能标签很快的场景,那么resolve()
的异步操作仍会执行,会导致组件卸载后依然执行this.setState
方法,导致内存泄露。 render
,componentDidMount
虽然是生命周期的两个方法,可以看作是同步执行(?,准确的说不是真正的同步,但是两个任务之间不会插入promise.then的执行,具体原理还得再研究)的,所以不存在this.state.AsyncComponent
会在两者执行之间的同时执行的问题。
通过对dva
源码的学习,收获了一些不一样的知识,分享给大家。