为什么我的 ko 计算的可观察量在其值更改时不更新绑定的 UI 元素

Why does my ko computed observable not update bound UI elements when its value changes?

本文关键字:更新 UI 绑定 元素 计算 ko 我的 观察 为什么      更新时间:2023-09-26

我正在尝试将cookie包装在计算的可观察量中(我稍后会将其变成受保护的可观察量(,并且我在计算的可观察量方面遇到了一些问题。 我认为对计算可观察量的更改将广播到已绑定到它的任何 UI 元素。

我创建了以下小提琴

JavaScript

var viewModel = {};
// simulating a cookie store, this part isnt as important
var cookie = function () {  
    // simulating a value stored in cookies
    var privateZipcode = "12345";
    return {
        'write' : function (val) { privateZipcode = val; }, 
        'read': function () { return privateZipcode; }
    }
}();
viewModel.zipcode = ko.computed({
        read: function () {
            return cookie.read();
        },
        write: function (value) {
            cookie.write(value);
        },
        owner: viewModel
    });
ko.applyBindings(viewModel);?

HTML

zipcode:
<input type='text' data-bind="value: zipcode"> <br />
zipcode: 
<span data-bind="text: zipcode"></span>?

我没有使用可观察量来存储privateZipcode因为它实际上只是在 cookie 中。 我希望ko.computed能够提供我需要的通知和绑定功能,尽管我看到的大多数示例ko.computed最终都使用了幕后的ko.observable

将值

写入我的计算可观察量的行为不应该向绑定到其值的 UI 元素发出信号吗? 这些不应该只是更新吗?

解决方法

有一个简单的解决方法,我只需在 cookie 存储的一侧使用ko.observable,使用它就会触发对我的 DOM 元素的所需更新,但这似乎完全没有必要,除非ko.computed缺少 ko.observable 具有的信号/依赖类型功能。

我的解决方法小提琴,您会注意到唯一更改的是我添加了一个不用作存储的seperateObservable,其唯一目的是向 UI 发出基础数据已更改的信号。

// simulating a cookie store, this part isnt as important
var cookie = function () {  
    // simulating a value stored in cookies
    var privateZipcode = "12345";
    // extra observable that isnt really used as a store, just to trigger updates to the UI
    var seperateObservable = ko.observable(privateZipcode);
    return {
        'write' : function (val) { 
            privateZipcode = val; 
            seperateObservable(val);
        }, 
        'read': function () { 
            seperateObservable();
            return privateZipcode; 
        }
    }
}();

这是有道理的,并且按照我的预期工作,因为viewModel.zipcode取决于seperateObservable,并且更新应该(并且确实(向 UI 发出更新信号。 我不明白的是,为什么不调用ko.computed上的 write 函数来指示 UI 进行更新,因为该元素绑定到该ko.computed

怀疑我可能必须在淘汰赛中使用一些东西来手动表示我的ko.computed已更新,我对此很好,这是有道理的。 我只是无法找到一种方法来实现这一点。

叹息,我发现有人有我完全相同的问题

如果依赖可观察量在写入时没有通知订阅者,为什么它们 甚至懒得在阅读时做吗?它们被添加到可观察量列表中 并订阅,但随后它们从未触发更新。那么什么是 订阅它们的意义何在?

Ryan Niemeyer回答:

我认为对于您的场景,依赖可观察量可能不是 适合工作的工具。 从属设置可观察量以检测 读取函数中的依赖项,并在任何情况下重新评估/通知 的依赖关系发生变化。 在可写依赖可观察中, 写入函数实际上只是一个拦截写入并允许的地方 您可以设置任何必要的可观察量,以便您的读取函数 将返回正确的值(写入通常与读取相反 在大多数情况下,除非您要转换值(。

对于您的情况,我个人会使用可观察量来表示 值,然后手动订阅该可观察量以更新 原始值(您可能无法控制的值(。

就像:http://jsfiddle.net/rniemeyer/Nn5TH/

所以看起来这个小提琴将是一个解决方案

var viewModel = {};
// simulating a cookie store, this part isnt as important
var cookie = function () {  
    // simulating a value stored in cookies
    var privateZipcode = "12345";
    return {
        'write' : function (val) { 
            console.log("updated cookie value with: " + val);
            privateZipcode = val; 
        }, 
        'read': function () { 
            return privateZipcode; 
        }
    }
}();
viewModel.zipcode = ko.observable(cookie.read());
// manually update the cookie when the observable changes
viewModel.zipcode.subscribe(function(newValue) {
   cookie.write(newValue);   
});
ko.applyBindings(viewModel);​

这是有道理的,而且使用起来更简单。 总的来说,我不确定将 cookie 视为可观察对象有多好,因为服务器可以在 ajax 请求等中编辑它。

尝试将内部私有邮政编码设置为可观察的。看这里: http://jsfiddle.net/KodeKreachor/fAGes/9/