Knockout.js:初始为undefined的可观察属性切换样式失效问题
问题分析与解决方案
你遇到的问题核心在于Knockout无法自动追踪后续动态添加的可观察属性,以及当前的样式绑定没有正确订阅属性变化:
- 初始时
task对象里没有urgent属性,Knockout在初始化绑定的时候,只会对当时存在的属性建立依赖追踪。当你点击后才给data添加urgent这个observable,Knockout并不会自动重新扫描这个属性,所以样式绑定里的表达式不会重新计算。 - 你的样式绑定表达式
$data.urgent !== undefined是一个一次性的判断——只有在绑定初始化时会执行一次,后续即使urgent被添加,这个表达式也不会再次求值,因为它没有订阅任何可观察属性的变化。
修复方案:提前初始化可观察属性
最稳妥的方式是在创建task对象时就初始化urgent可观察属性,初始值可以设为false或者null,这样Knockout从一开始就能监听它的变化:
修改后的ViewModel代码:
function ViewModel_icon() { self2 = this; self2.tasks = ko.observableArray([ { task: ko.observable("Task1"), time: ko.observable("Saturday, 5 May 2018"), status: ko.observable("active"), priority: ko.observable("medium"), urgent: ko.observable(false) // 提前初始化urgent为可观察属性 } ]); self2.checkUrgent = function (data){ data.urgent(true); // 点击后直接修改可观察属性的值 } } var VM1 = new ViewModel_icon(); ko.applyBindings(VM1);
对应的HTML样式绑定也需要调整,因为现在urgent是可观察属性,需要用()获取它的值:
<div id="icon" data-bind='foreach: tasks'> <i class="fas fa-exclamation-circle" data-bind='click: $parent.checkUrgent, style: {"color" : urgent() ? "red" : "black"}'> </i> </div>
为什么这样能解决问题?
- 提前初始化
urgent为可观察属性,Knockout在绑定初始化时就会建立对它的依赖追踪。 - 样式绑定里的
urgent()会订阅这个可观察属性的变化,当点击修改它的值时,Knockout会自动重新计算样式表达式,更新元素颜色。
如果你确实需要动态添加属性(不推荐)
如果因为某些原因必须动态添加urgent属性,你可以在添加后手动触发绑定更新,或者使用ko.mapping插件来处理动态对象。不过这种方式会增加复杂度,不如提前初始化属性来得简洁可靠。
内容的提问来源于stack exchange,提问作者Alonad
相关产品推荐
相关产品推荐

