AngularJS中ng-if切换表格行编辑态时两个单元格同时显示闪烁问题
根因分析
你遇到的闪烁本质是两个互斥ng-if的DOM操作没有同步执行:AngularJS脏检查周期中,新元素的插入和旧元素的移除拆分到了两个不同的任务队列,加上如果项目引入了ngAnimate模块,默认会给ng-if的元素添加300ms的离场延迟,就会出现短时间双元素共存的情况,你观察到的jQuery内部逻辑卡顿,本质是事件分发和Angular脏检查的执行顺序冲突导致的时间差被放大。
可落地解决方案
方案1:用ng-switch替换互斥ng-if(优先推荐)
ng-switch的分支渲染/销毁是在同一个DOM操作批次中同步执行的,天然避免了互斥元素的共存问题,改动量极小:
<TABLE-CELL class="value-col" ng-switch on="readtime.editableRow"> <!-- 编辑态分支 --> <input type="text" ng-switch-when="true" name="readingTime" ng-model="<data model>" ng-disabled="<param>" ng-change="<function>" ng-class="<classes>" /> <!-- 只读态分支 --> <input type="text" ng-switch-when="false" placeholder="{{<data model>}}" ng-class="<classes>" /> </TABLE-CELL>
该方案完全保留了ng-if的按需渲染特性,不会额外预生成元素,性能和你原有方案完全一致。
方案2:禁用对应元素的AngularJS动画(如果引入了ngAnimate)
如果项目引入了ngAnimate模块,默认的离场动画会导致旧元素延迟销毁,直接给两个单元格添加ng-animate-disabled类即可关闭动画,实现同步销毁:
<TABLE-CELL class="value-col ng-animate-disabled" ng-if="readtime.editableRow === true"> <!-- 其余内容不变 --> <TABLE-CELL class="value-col ng-animate-disabled" ng-if="readtime.editableRow === false">
也可以全局配置$animateProvider,批量禁用表格元素的动画:
app.config(['$animateProvider', function($animateProvider) { $animateProvider.classNameFilter(/^(?!(value-col)).*$/); }]);
方案3:单元素动态切换属性(性能最优)
完全移除两个互斥单元格的结构,只用单个input动态切换属性,从根源上避免双元素共存的可能:
<TABLE-CELL class="value-col"> <input type="text" name="readingTime" ng-model="readtime.editableRow ? <data model> : null" ng-disabled="!readtime.editableRow || <param>" ng-change="readtime.editableRow && <function>()" ng-class="<classes>" ng-attr-placeholder="{{!readtime.editableRow ? <data model> : ''}}" /> </TABLE-CELL>
该方案只生成一个DOM元素,切换状态时仅修改属性,没有DOM增删开销,性能比原有方案更好。
方案4:统一事件上下文
如果你的行点击事件是用jQuery绑定的,会导致事件回调脱离Angular的脏检查上下文,增大DOM操作的时间差。把点击事件切换为Angular原生的ng-click绑定,保证状态修改和DOM更新在同一个脏检查周期内执行即可。
内容的提问来源于stack exchange,提问作者Reverend Bubbles
相关产品推荐
相关产品推荐

