在Knockout中我有可观察变量location
。它的类型为LocationEdit
。此viewModel具有可观察而非字段。
我收集了字段名称:fields
。对于每个字段,我想重置location
fields.forEach(field => {
if (this.uniqueField(locs, field)) {
if (ko.isObservable(this.location()[field])) {
this.location()[field](locs[0][field]);
} else {
this.location()[field] = locs[0][field];
}
}
});
为了使这段代码更简单(删除if-clauses),我能以某种方式在一行中将值设置为this.location()[field]
吗?
答案 0 :(得分:2)
您可以使用条件运算符(... ? ... : ... ;
),尽管它没有太大变化:
fields.forEach(field => {
if (this.uniqueField(locs, field)) {
ko.isObservable(this.location()[field]) ? this.location()[field](locs[0][field]) : this.location()[field] = locs[0][field];
}
});
或者你可以写一个函数:
function upd(arr, index, val) {
ko.isObservable(arr[index]) ? arr[index](val) : arr[index] = val;
}
用法:
fields.forEach(field => {
if (this.uniqueField(locs, field)) {
upd(this.location(), field, locs[0][field]);
}
});
请参阅 demo 。
您甚至可以将此功能添加到ko
:
if(typeof ko.updatePotentialObservable == 'undefined')
ko.updatePotentialObservable = function (arr[index], val) {
ko.isObservable(obj) ? arr[index](val) : arr[index]= val;
}
用法:
fields.forEach(field => {
if (this.uniqueField(locs, field)) {
ko.updatePotentialObservable(this.location(), field, locs[0][field]);
}
});
请参阅其他 demo
答案 1 :(得分:0)
说实话,我认为Gôtô的答案肯定是你最好的选择。基本上,您需要创建一个类似于ko.unwrap
的效用函数,但设置一个值。
但是既然你说“也想找到另一个解决方案”,这里有一个不同的效用函数。我认为代码中最令人困惑的部分是对locs[0][field]
和this.location()[field]
的回复。我想要一些有这个签名的东西:
reset(source, target, keys);
因此,在您的代码中,您可以这样做:
reset(
this.location(),
locs[0],
fields.filter(f => this.uniqueField(locs, f))
);
现在,写这个方法,我最终得到了这个:
const mergePropsObs = (function() {
// Return a method for setting a specific property in object
const getSetter = obj => prop => ko.isObservable(obj[prop])
? obj[prop]
: val => obj[prop] = val;
// Return unique keys for two objects
// (I went with a quick oneliner; there are many ways to do this)
const allKeys = (obj1, obj2) =>
Object.keys(Object.assign({}, obj1, obj2));
return (base, ext, onlyProps) => {
const props = onlyProps || allKeys(base, ext);
const values = props.map(p => ko.unwrap(ext[p]));
props
.map(getSetter(base))
.forEach((setter, i) => setter(values[i]));
};
}());
var base = { a: 1, b: ko.observable(2), c: 5 };
mergePropsObs(
base,
{ a: 2, b: 3 },
["a", "b"]);
console.log(base.a);
console.log(base.b());
console.log(base.c);
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
此实用程序方法可与上述签名一起使用。当您不提供字段名称数组时,它也有一个后备。