Javascript ko.当依赖值发生变化时,不进行计算
我创造了这把小提琴 该视图不会更新“搜索”和“创建”按钮的启用状态。只有在用户选择产品类时才会发生,但在用户更改组件的值时也必须发生 该视图是一个搜索视图,使用户能够搜索由依赖于所选产品类别的组件标识的产品 视图模型:Javascript ko.当依赖值发生变化时,不进行计算,javascript,jquery,data-binding,knockout.js,computed-observable,Javascript,Jquery,Data Binding,Knockout.js,Computed Observable,我创造了这把小提琴 该视图不会更新“搜索”和“创建”按钮的启用状态。只有在用户选择产品类时才会发生,但在用户更改组件的值时也必须发生 该视图是一个搜索视图,使用户能够搜索由依赖于所选产品类别的组件标识的产品 视图模型: /// ProductClass function ProductClassModel() { this.Id = 0; this.FullCode = ""; this.Name = ""; this.EntitiClass = "";
/// ProductClass
function ProductClassModel() {
this.Id = 0;
this.FullCode = "";
this.Name = "";
this.EntitiClass = "";
this.CompClasses = [];
}
/// Component class that is part of a product class
function ComponentClassModel() {
this.Id = 0;
this.FullCode = "";
this.Name = "";
this.ProductClassId = 0;
this.ComponentClass = "";
}
/// The product, it is the composition of a product class with values for each of its components
function ProductModel() {
this.Id = ko.observable(0);
this.Uid = ko.observable("");
this.FullCode = ko.observable("");
this.Name = ko.observable("");
this.EntitiClass = ko.observable("");
this.Components = ko.observable([]);
}
/// ComponentValue is a class of component with a value (actually an instance of that class of component)
function ComponentValueModel() {
this.Id = ko.observable(0);
this.FullCode = ko.observable("");
this.Name = ko.observable("");
this.ProductClassId = ko.observable(0);
this.ProductId = ko.observable(0);
this.ComponentClass = ko.observable("");
this.Value = ko.observable();
}
/// Wrapper of ComponentValueModel with convenient observable properties (We cannot modify the original ComponentValueModel because it is extern)
function ComponentStateViewModel(prodcomp) {
var self = this;
console.log("CREA ComponentStateViewModel " + prodcomp);
self.value = prodcomp.Value();
self.component = prodcomp;
self.changed = ko.observable(false);
self.found = ko.observable(false);
self.searched = ko.observable(false);
self.required = true;
self.isCreatable = ko.computed(function () {
return self.searched() && !self.found();
});
self.isDefined = ko.computed(function () {
return self.component.Value() !== undefined;
});
self.component.Value.subscribe(function () {
var newval = self.component.Value();
if (newval !== self.value) {
self.changed(true);
self.found(false);
self.searched(false);
self.value = newval;
}
});
}
/// View model
function ProductViewModel() {
var self = this;
self.customerId = ko.observable(111);
self.prodClasses = ko.observable([]);
self.currentProdClass = ko.observable();
self.currentProd = ko.observable();
self.currentUid = ko.observable();
self.productsFound = ko.observableArray();
self.componentStates = ko.observableArray();
self.productFound = ko.computed(function () {
var prod = self.currentProd();
return self.prodClassSelected && (prod !== undefined && prod.Uid() !== undefined);
});
self.customerSelected = ko.computed(function () {
return self.customerId() > 0;
});
self.prodClassSelected = ko.computed(function () {
return self.currentProdClass() !== undefined;
});
self.canSearch = ko.computed(function () {
if (!self.prodClassSelected() || !self.productFound()) {
return false;
}
var inuid = self.currentUid();
var puid = self.currentProd().Uid();
if ((inuid !== undefined) && (inuid !== puid) && (inuid.length > 5)) {
return true;
}
var comps = self.componentStates();
for (var i = 0; i < comps.length; i++) {
var c = comps[i];
if (c.isDefined && !c.searched) {
return true;
}
}
return false;
});
self.canCreate = ko.computed(function () {
if (!self.prodClassSelected() || self.productFound()) {
return false;
}
var cstates = self.componentStates();
for (var i = 0; i < cstates.length; i++) {
var cm = cstates[i];
if (!cm.component.Value()) {
return false;
}
if (!cm.isCreatable()) {
return false;
}
}
return true;
});
self.clear = function () {
self.componentStates([]);
var c = self.currentProdClass();
if (c !== undefined) {
self.currentUid(undefined);
self.currentProd(undefined);
}
};
self.initialize = function (compClassesData) {
self.prodClasses(compClassesData);
};
self.currentUid.subscribe(function () {
var uid = self.currentUid();
if (uid === undefined) {
return;
}
var prod = self.currentProd();
if ((prod === undefined) || (prod.Uid() !== uid)) {
if (uid.length < 5) {
return;
}
self.currentProd(new ProductModel());
}
});
self.currentProdClass.subscribe(function () {
self.clear();
var c = self.currentProdClass();
if (c === undefined) {
return;
}
var psearch = new ProductModel();
psearch.FullCode(c.FullCode);
psearch.Name(c.Name);
psearch.EntitiClass(c.EntitiClass);
for (var i = 0; i < c.CompClasses.length; i++) {
var cca = c.CompClasses[i];
var comp = new ComponentValueModel();
comp.FullCode(cca.FullCode);
comp.Name(cca.Name);
comp.ProductClassId(cca.ProductClassId);
comp.ComponentClass(cca.ComponentClass);
psearch.Components().push(comp);
self.componentStates.push(new ComponentStateViewModel(comp));
}
self.currentProd(psearch);
self.currentUid(psearch.Uid());
});
self.searchProduct = function () {
var compfilter = [];
var comps = self.currentProd().Components();
for (var i = 0; i < comps.length; i++) {
var c = comps[i];
if ((c.Value() !== undefined) && (c.Value() !== "")) {
var filter = new ComponentValueModel();
filter.FullCode(c.FullCode());
filter.ComponentClass(c.ComponentClass());
filter.Value(c.Value());
compfilter.push(filter);
}
}
};
self.createProduct = function () {
// TODO
};
}
问题在于“搜索”和“创建”按钮。第一个是由一个涉及多个观察值的计算函数启用或禁用的,但我感兴趣的是ComponentValueModel类组件的值。值:
<button data-bind="click: searchProduct, enable: canSearch()">Search</button>
我希望启用或禁用此按钮的代码在ProductViewModel.canSearch计算函数中定义:
self.canSearch = ko.computed(function () {
if (!self.prodClassSelected() || !self.productFound()) {
return false;
}
var inuid = self.currentUid();
var puid = self.currentProd().Uid();
if ((inuid !== undefined) && (inuid !== puid) && (inuid.length > 5)) {
return true;
}
var comps = self.componentStates();
for (var i = 0; i < comps.length; i++) {
var c = comps[i];
if (c.isDefined && !c.searched) {
return true;
}
}
return false;
});
似乎ko没有通知可观察组件中的值的变化。任何帮助都将不胜感激 尝试删除enable-bind:enable:canSearchI中的括号。如果定义了c,我认为您缺少了对两个组件属性的可观察的取消引用!c、 搜索。第一个是计算的,第二个是可观察的,它们都没有必要访问它们的值。此外,我还必须通过将计算函数ProductViewModel.productFound向上移动来重构代码,使其在调用之前保持不变,否则就不会发生类似self.productFound这样的错误。