xinglie / xinglie.github.io

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

magix当中的渲染设计 #101

Open xinglie opened 2 years ago

xinglie commented 2 years ago

本篇不谈实现,只谈思路

从父到子逐层渲染

如果我们要在当前view中渲染其它view,在magix当中我们这样写即可

<div class="card">
    <mx-vframe src="./user/info"/>
</div>

magix在渲染上述模板片断时,采用仅聚焦当前view的思路,即渲染时,不关心也不会预处理子view:./user/info。而是把当前viewhtml片断真实渲染到页面上后,才会查找当前的子view,然后加载渲染。

这与其它的常见框架不同,比如react

<div class="card">
    <UserInfo/>
</div>

react编译成虚拟dom是类似这样的函数调用

React.createElement('div',{class:"card"},
    React.createElement(UserInfo)
)

对于这样的代码执行,是先构建子节点,最后才构建父节点。基于这点,后续在react中比较容易实现的功能在magix当中均难实现。

不过有些功能在magix当中却比其它框架容易实现。

不留痕迹

通常view背后都需要接口的支撑,即区块从magix开始加载、实例、展示是有时间差的,如果我们要在这个过程中添加一个loading动画,在magix中只需要像下面这样做

<div class="card">
    <mx-vframe src="./user/info">
        <div class="loading"></div>
    </mx-vframe>
</div>

<mx-vframe>标签间加入任何你想要的提示内容,在子view内容真正展示前,均会展示这个提示内容,这在做子view动态切换时非常有用,比如

<div class="card">
    <mx-vframe src="{{=dynamicViewPath}}">
        <div class="loading"></div>
    </mx-vframe>
</div>

如果把src属性设置为一个变量,则magix会动态的根据变量的值去渲染相应的view。假设dynamicViewPath初始值为a,后变更为b,则在ab的切换过程中,magix会在销毁a这个view后,把<mx-vframe>标签间的内容恢复到渲染前的状态,如果你在<mx-vframe>标签间加入了loading动画,此时会显示出来,等到b真正渲染后,b view的内容会把loading替换掉。这个过程是magix自动处理的,开发者只需要在<mx-vframe>标签间写上相应的loading提示即可。

如果后续销毁了b viewmagix依然会把<mx-vframe>标签间的初始内容恢复,即渲染前什么状态,销毁后恢复到什么状态,此谓不留痕迹。

这样的设计虽然方便了开发者,又会引入其它问题

闪烁

前述的<mx-vframe>标签间允许添加提示内容,且magix会在销毁时还原的设计,在某些情况下方便,却会引入闪烁的问题。

比如并不是每个场景都需要加loading提示,也不是每个子view加载都会有异步。

<div class="card">
    <mx-vframe src="{{=dynamicViewPath}}"/>
</div>

还是以从a变到b为例,a销毁后,因为<mx-vframe>标签间无内容,magix会清空,然后再实例化b,如果b模块已经加载过,且b内部不需要异步展示界面,过程简化:a销毁->清空mx-vframe节点->展示b内容,这在某些浏览器下会闪烁,理想的情况是a销毁->展示b内容

mx-reset

magix角度是无法确切知道view到底是否能立即展示,即是否有异步的存在。理想情况下有异步的view我们给出loading提示,无异步的view我们不应该清空节点,应该直接替换,避免闪烁

目前从magix的角度给出开发者可控制的属性,即mx-reset,如

<div class="card">
    <mx-vframe mx-reset src="{{=dynamicViewPath}}">
        <div class="loading"></div>
    </mx-vframe>
</div>

默认所有view销毁时,不再清空节点内容,只有像有异步存在,可能有loading动画的场景下,开发者添加mx-reset属性,才走销毁->恢复mx-vframe节点初始内容->显示其它view的渲染流程,否则直接走销毁->显示其它view