使用过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源码的学习,收获了一些不一样的知识,分享给大家。