gpt4 book ai didi

javascript - 有没有办法告诉 knockout 等到定义 View 模型后再重新计算计算值?

转载 作者:IT王子 更新时间:2023-10-29 03:23:16 26 4
gpt4 key购买 nike

我有一个复杂的 View 模型,它是几百行 javascript 代码,具有大量可观察属性、计算可观察属性、可写计算可观察属性和函数。所以管理这个是一个相当大的挑战。

我不得不处理的一个烦人的问题是计算的可观察量在您定义它时立即计算出来。因此,在定义可观察对象时使用尚未在 View 模型中定义的变量会导致错误,指出该变量尚未定义。它是...就在文件的后面。

这是一个人为的例子:

function ViewModel1​(args) {
var self = this;

self.firstName = ko.observable(args.firstName);
self.lastName = ko.observable(args.lastName);
self.fullName = ko.computed(function () {
return self.firstName() + ' ' + self.lastName();
});
}

function ViewModel2​(args) {
var self = this;

self.fullName = ko.computed(function () {
// uh oh, where's firstName?
return self.firstName() + ' ' + self.lastName();
});
self.firstName = ko.observable(args.firstName);
self.lastName = ko.observable(args.lastName);
}

使用 ViewModel1 不会有任何问题。在定义 fullName 时,定义了 firstNamelastName,因此它按预期工作。使用 ViewModel2 将不起作用。计算函数中会出现错误,指出 firstName 未定义。

到目前为止,我一直在做的是确保在定义所有因变量之后定义所有计算的可观察量。这样做的问题是,当我宁愿将相关变量定义在一起时,事情会在看似随机的地方定义。

我想出的一个很好的解决方案是定义一个“正在初始化”的可观察对象设置为 true 并让所有计算的可观察对象测试它是否仍在初始化,并在初始化时计算并返回值't。这样,就不会尝试访问当前 undefined variable 。

function ViewModel3(args) {
var self = this;
var initializing = ko.observable(true);

self.fullName = ko.computed(function () {
if (!initializing()) {
return self.firstName() + ' ' + self.lastName();
}
});
self.firstName = ko.observable(args.firstName);
self.lastName = ko.observable(args.lastName);

initializing(false);
}

但这对我来说不是很实用。我有很多计算的可观察量,所以在所有这些中都这样做会使它变得非常臃肿,记住我有很多这样的东西。节流它似乎没有什么不同。

有没有办法告诉 knockout 在尝试计算计算的可观察值之前等待?还是有更好的方法来构建我的代码来处理这个问题?

我可能会创建一些辅助函数来管理初始化逻辑,但我仍然必须更改所有计算的可观察定义。我想我可以通过 monkey patch knockout 来添加这个初始化逻辑,因为我不知道 knockout 有这样的选项,我可能会这样做。我之前查看过计算可观察量的来源,但我不知道其他地方是否已经有设置。

jsfiddle demo

最佳答案

Computed observables 接受一个 deferEvaluation 选项,该选项阻止初始评估发生,直到某些东西实际尝试检索计算的值。

你可以这样定义它:

self.fullName = ko.computed({
read: function() {
return self.firstName() + " " + self.lastName();
},
deferEvaluation: true
});

为了完整起见,您还可以像这样指定它:

this.fullName = ko.computed(function() {
return this.firstName() + " " + this.lastName();
}, this, { deferEvaluation: true });

或者你可以像这样包装它:

ko.deferredComputed = function(evaluatorOrOptions, target, options) {
options = options || {};

if (typeof evaluatorOrOptions == "object") {
evaluatorOrOptions.deferEvaluation = true;
} else {
options.deferEvaluation = true;
}

return ko.computed(evaluatorOrOptions, target, options);
};

关于javascript - 有没有办法告诉 knockout 等到定义 View 模型后再重新计算计算值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11569341/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com