Knockout自定义绑定包装器问题:输入变更未触发Observable订阅
Knockout自定义textInput绑定不更新Observable的问题解决
刚接触Knockout遇到这种问题很正常,我帮你分析下问题出在哪,再给你修正后的代码:
问题根源
你在myBind的init函数里创建了一个局部的test observable,这个变量只在init函数执行的瞬间存在,执行完后就会被JavaScript的垃圾回收机制处理掉。而且你调用ko.bindingHandlers.textInput.init的时候,直接传了test这个observable,但textInput绑定期望的是一个返回可观察对象的函数(也就是valueAccessor的格式),这就导致textInput无法正确和你的observable建立双向绑定的关联,自然输入内容时不会更新。
修正后的代码
首先我们要让自定义绑定能正确关联可观察对象,不管是外部传入的还是内部初始化的:
ko.bindingHandlers.myBind = { init: function(element, valueAccessor, allBindings) { // 获取绑定的可观察对象,如果外部没传,就创建一个带初始值"abc"的 var observable = valueAccessor() || ko.observable("abc"); // 如果外部传入的observable是空的,设置初始值"abc" if (!observable.peek()) { observable("abc"); } // 订阅变化,打印新值 observable.subscribe(function(newVal){ console.log(newVal); }); // 调用textInput的init方法,这里要传递一个返回observable的函数,符合valueAccessor的格式 ko.bindingHandlers.textInput.init(element, function() { return observable; }, allBindings); }, update: function(element, valueAccessor, allBindings) { // 调用textInput的update方法,确保observable的值变化时能同步到输入框 ko.bindingHandlers.textInput.update(element, valueAccessor, allBindings); } }; // 可以创建一个viewModel来绑定外部的observable(推荐方式) var viewModel = { inputText: ko.observable() }; ko.applyBindings(viewModel);
对应的HTML可以这样写:
<!-- 绑定到viewModel里的inputText,初始值会被设为"abc" --> <input data-bind="myBind: inputText" /> <!-- 如果不需要外部viewModel,也可以直接传带初始值的observable --> <input data-bind="myBind: ko.observable('abc')" />
关键调整点
- 不再使用局部的observable,而是基于
valueAccessor来获取或创建可观察对象,这样绑定的上下文是正确的 - 调用textInput的init时,传递的是一个返回observable的函数,符合Knockout绑定的要求
- 添加了
update方法,调用textInput的update来确保双向绑定的同步(当observable的值从代码里改变时,输入框也会更新)
内容的提问来源于stack exchange,提问作者Nirbhay Jha
相关产品推荐
相关产品推荐

