xinglie / xinglie.github.io

blog
https://xinglie.github.io
153 stars 22 forks source link

组件参数的优化 #55

Open xinglie opened 4 years ago

xinglie commented 4 years ago

在浏览器内,组件的实例化与销毁通常是比较耗费资源的。尤其像现的页面,通常有几十上百个组件都很正常。 当我们通过某种机制比如虚拟DOM更新界面时,我们应该避免过多的销毁再新建组件,能复用的复用,能不动的不动,我们该如何做到最小化的操作组件呢?

<div>
    {{=title}}
</div>
<mx-vframe src="./list" *list="{{@ list }}" class="{{showLoading}}?loading">
    {{=loadingText}}
</mx-vframe>

引起一个组件变化的3个地方

  1. 参数变化,如list
  2. 属性变化,如class
  3. 子节点变化,如loadingText

这三处变化均需要通知./list这个组件进行响应,其中2,3两点非常容易实现,但参数变化却很难,为什么?像上述代码不就是list变化就要更新组件吗?

因为参数可以来自任意地方,如

{{set list=user.permissions}}
<div>
    {{=title}}
</div>
<mx-vframe src="./list" *list="{{@ list }}" class="{{showLoading}}?loading">
    {{=loadingText}}
</mx-vframe>

来自某一个变量,这种需要识别user.permissions有变化才需要更新

<div>
    {{=title}}
</div>
{{each outerList as list}}
<mx-vframe src="./list" *list="{{@ list }}" class="{{showLoading}}?loading">
    {{=loadingText}}
</mx-vframe>
{{/each}}

来自循环,这个场景下需要outerList变化才更新组件

如何通过引用的地方{{@ list }}知道这个list来自哪里,然后针对这个对象进行有无变化识别即可?

JS AST

https://astexplorer.net/

我们可以利用js的语法解析器得到整个ast,从而可以知道变量的引用关系,之前在局部刷新与模板中讲到过变量的追踪,从而把某个变量与某一片HTML关联起来,有变量有变化时,只更新部分HTML

在转向dom diff后,该方案被废弃了,但里面的变量识别、变量赋值跟踪等功能,可以和我们的组件结合起来,对于前述的组件参数变量引用,则可以通过该技术把组件与最终变化的对象关联起来,从而实现只有相应的数据变化时,组件才会真正的被更新,不管中间这个变量被赋值转换多次次。