我陷入了需要在子元素中随处可见的自定义变量的区域,例如我们可以引用的$ parents,$ parent。 例如:
<div data-bind:"addThisVariable: { name: '$hello', value: somethingTimeConsuming() }">
<div data-bind="foreach: something">
<span data-bind="text: $hello.stringReference">
</span>
</div>
</div>
我想知道它是否已经与Knockout一起提供,或者是否有人知道如何实现这一目标。
但是在淘汰赛中,对于我声明的所有情境和儿童情境。 所以我可以完成潜在的耗时任务,而不必每次都重新运行它们。
编辑:我不希望“with:$ something”绑定不能回答我的答案
它就像一个临时变量,我需要填充子上下文,就像我们为
做的那样.forEach(function(item){
var somethingCalculated = 1234;
item.someArray.forEach(function(subItem) {
var somethingElse = somethingCalculated + 567;
}
})
答案 0 :(得分:3)
前段时间,我为自己创建了一个名为let
的简单绑定,可以完成您想要的操作。这是:
ko.bindingHandlers['let'] = {
init: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
// Make a modified binding context, with extra properties, and apply it to descendant elements
var innerContext = bindingContext.extend(valueAccessor);
ko.applyBindingsToDescendants(innerContext, element);
return { controlsDescendantBindings: true };
}
};
ko.virtualElements.allowedBindings['let'] = true;
您可以这样使用它:
<div data-bind:"let: { $hello: somethingTimeConsuming() }">
<div data-bind="foreach: something">
<span data-bind="text: $hello.stringReference">
</span>
</div>
</div>
ko.bindingHandlers['let'] = {
init: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
// Make a modified binding context, with extra properties, and apply it to descendant elements
var innerContext = bindingContext.extend(valueAccessor);
ko.applyBindingsToDescendants(innerContext, element);
return { controlsDescendantBindings: true };
}
};
ko.virtualElements.allowedBindings['let'] = true;
(function() {
var vm = {
foo: ko.observable("foo"),
bar: ko.observable("bar"),
list: ko.observableArray([
'one', 'two', 'three'
])
};
vm.hello = ko.pureComputed(function() {
return vm.foo() + vm.bar();
});
ko.applyBindings(vm);
})();
<script src="//cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<div data-bind="let: { $hello: hello() }">
<div data-bind="foreach: list">
<span data-bind="text: $data"></span><span data-bind="text: $hello"></span>
</div>
</div>
答案 1 :(得分:2)
这两个选项都没有给你JavaScript with
(但是,JavaScript的with
有一些非常重要的维护问题),但这里有几个选项:
您最好的选择可能是(比如说)容器甚至是根VM。
yourVm.hello = ko.computed({
pure: true, // If it is, that is
read: function() {
// complex stuff here
}
});
示例:
(function() {
"use strict";
var vm = {
foo: ko.observable("foo"),
bar: ko.observable("bar"),
list: ko.observableArray([
'one', 'two', 'three'
])
};
vm.hello = ko.computed({
pure: true,
owner: this,
read: function() {
return this.foo() + this.bar();
}
});
ko.applyBindings(vm, document.body);
})();
<script src="//cdnjs.cloudflare.com/ajax/libs/knockout/3.1.0/knockout-min.js"></script>
<div data-bind="foreach: list">
<span data-bind="text: $data"></span><span data-bind="text: $parent.hello"></span>
</div>
如果计算出的可观察值改变了值,则只会重新估算计算值。
如果你把它放在根上,那么$root.hello
将始终引用它。
但我认为可能创建一个自定义绑定,使用语法非常类似于你所显示的,但我不认为我会推荐它。沿着这些方向的东西(完全未经测试 - 呵呵,whaddyaknow,它有效,见下文):
ko.bindingHandlers.addThisVariable = {
update: function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
var value = ko.unwrap(valueAccessor());
bindingContext.$data[ko.unwrap(value.name)] = ko.unwrap(value.value);
}
};
示例(但同样,我真的认为我会使用计算机):
(function() {
"use strict";
ko.bindingHandlers.addThisVariable = {
update: function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
var value = ko.unwrap(valueAccessor());
bindingContext.$data[ko.unwrap(value.name)] = ko.unwrap(value.value);
}
};
var vm = {
foo: ko.observable("foo"),
bar: ko.observable("bar"),
list: ko.observableArray([
'one', 'two', 'three'
])
};
ko.applyBindings(vm, document.body);
})();
<script src="//cdnjs.cloudflare.com/ajax/libs/knockout/3.1.0/knockout-min.js"></script>
<div data-bind="addThisVariable: { name: '$hello', value: foo() + bar() }, foreach: list">
<span data-bind="text: $data"></span><span data-bind="text: $parent.$hello"></span>
</div>
这只会将其添加到当前VM(因此需要with
或foreach
或其他任何内容的<{1}}或$parent
内的}绑定 ),但它仍然提供了一些你可以在HTML块中引用的本地东西。
答案 2 :(得分:1)
Knockouts foreach
绑定具有as
选项,可以执行您想要的操作。如果你有一个“某事”的数组,并且你希望能够将它们引用为$something.whatever
,那么
<!-- ko foreach: {data: arrayOfSomethings, as: '$something'} -->
<span data-bind="text: $something.foo"></span> <!-- works in any child context -->
<!-- /ko -->
另一方面,如果你只有一个“东西”......老实说,我可能会推荐Michael Best的let
绑定......但如果你只想要一些有用的东西,不需要自定义绑定处理程序...
<!-- ko foreach: {data: [something], as: '$something'} --> <!-- ugly but it works -->
<span data-bind="text: $something.foo"></span> <!-- works in any child context -->
<!-- /ko -->
(旁注,我实际上不建议使用“$ something”作为你的名字;我会留下$ knockout-defined东西的前缀,只是把你的东西称为“某事”;亲自)