老ER里refresh 为啥只刷新控件,而不重载render整个 tpl
Opened this issue · 1 comments
R;T
首先,声明的是这个问题,提到这个Repo里可能不太合适,因为,我发现现在的ER里都没有 refresh 方法了,不过,希望各位大大指点,索性就提到这个里面了。
好了,回到正题:
之所以提出这个问题,是因为我在实际使用过程中遇到这样的问题。
如上图所示,现在的实际情况是,第一个框里的文字是模板变量映射model的值;第二个框是引入 echarts 绘制的图表。那么问题来了,挖掘机。。。(哦,跑题了)
当季度标签切换的时候整个model将会刷新,从而引起两个地方的联动,一个是紧接季度标签下的收入标签表格以及第一个红框中的文字;另一个就是 echarts 绘制的图表。
然后,一开始我就想当然的在 Action 中使用了 me.refresh() ,写好后,我开心的按下了F5
,开始切换季度标签,等待奇迹的发生,然后,等等,貌似只有表格刷新了。难道是我的使用姿势不对?不禁怀疑自己是不是用错地方了,然后回去翻了一下之前的代码,“没问题啊!之前也是这么写的!”,再然后,看了一下源代码,就知道 refresh 只刷新了控件,没有按我主观的对于 refresh 的认识那样,对整个 page 进行刷新。Ps: 这里多说一点,我的理解是:当 Model 刷新时,View 中与 Model 对应的数据也应执行相应的刷新,而不仅仅限于控件。
陷入了困境了。
解决方案:
请教了一下高人,然后得知用onentercomplete
就能搞定了。coding !F5
,切换标签,奇迹发生了。
最后,那么还是那个问题,(不是挖掘机)为啥,this.refresh
不重新 render tpl
。进一步而言就是:当我触发Action refresh 的时候,Model 刷新了,但是 tpl 中映射的变量也应该刷新。
然后,可能也是我使用的问题,或者说这种提法是有问题,因此,不知各位怎么看吧。
Review 了三遍Post,还是不太确定是否完全表述清楚我的意思,能让各位明晰。😂😂😂
这是老ER的问题。新ER里其实也有相应的机制,只不过不在ER这个repo下了。
首先,这基于一种假设:我们认为页面不一定是需要全部变化的。比如我们进入一个列表页面,然后点击了第二页,这时列表的表头可以不用变化,只局部刷新表格的内容区域。要实现这样的场景,我们需要知道什么东西是可变化的。通常情况下,有两种做法:
- 自动法:当render时,抽析出模板中变量的部分。这种做法用起来比较方便,但实际上比较麻烦。首先变化的一定是页面中的DOM,但你render的时候面对的是字符串,你需要按相应的规则parse出变化的部分(对应的是什么变量,属于DOM中的什么部分,text还是attr等),才能方便的构建映射。后续更新时,对于复杂的数据结构,你可能需要做diff,这个开销是很大的。
- 手动法:手工标识哪些东西是可变的。这个听起来不太现实,使用太麻烦了。但老ER正是这么做的,不是全手工,但是基于了一些规则。
老ER的做法是:
- 视图渲染的步骤,在框架层面做了一层抽象,分成render和repaint。当页面首次进入时,进入render过程;当二次进入(hash的path部分不变,参数变化时),进入repaint过程。这个抽象便于在视图渲染中实现局部刷新。但是ER并没规定一定要做这事。
- 视图render的步骤是:通过模板引擎填充HTML -> 渲染UI组件(初始化组件 -> 在当前环境下保存组件的引用 -> 为组件填充数据 -> 调用组件的render方法)
- 在上面的步骤中,视图能够知道当前有哪些组件,每个组件使用哪些数据了。这时候后面的局部刷新就好做了。在视图repaint中,我们只对组件进行刷新,步骤如下:遍历所有组件 -> 填充数据 -> 调用组件的render方法。
从上面的几点可以看出来:
- 局部刷新是由UI组件完成的(一个Table组件,第二次render的时候,只刷数据区域还是刷新全部,这件事情交给Table组件来决定。一个Select,value变化时只刷新显示区域这种事情也是Select自己完成)
- 视图缓存也是UI组件完成的(数据不变的时候,视图是否重新刷新,这个逻辑也交给UI组件)
综上,对老ER和ESUI集成的默认方案来说,我们认为UI组件是数据显示与变化的载体
。对于你上面的case,建议使用Label组件来承载需要变化的红框文字内容。