如何在.computed()observable中使用knockout的$ parent / $ root伪变量? [英] How can I use knockout's $parent/$root pseudovariables from inside a .computed() observable?

查看:269
本文介绍了如何在.computed()observable中使用knockout的$ parent / $ root伪变量?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

knockout.js 绑定表达式中,我可以使用 $ data $ parent $ root 伪变量。当我使用 ko.computed observable

Inside a knockout.js binding expression, I can use the $data, $parent, and $root pseudovariables. How can I get the equivalent of those pseudovariables when I'm using a ko.computed observable declared in JavaScript?

我有一个带有子集合的父视图模型,父视图模型有一个 selectedChild 可观察。鉴于此,我可以使用数据绑定表达式为当前选择的子项添加CSS类:

I've got a parent viewmodel with a collection of children, and the parent viewmodel has a selectedChild observable. Given that, I can use databinding expressions to add a CSS class to whichever child is currently selected:

<ul data-bind="foreach: children">
    <li data-bind="text: name,
                   css: {selected: $data === $root.selectedChild()},
                   click: $root.selectChild"></li>
</ul>
<script>
vm = {
    selectedChild: ko.observable(),
    children: [{name: 'Bob'}, {name: 'Ned'}],
    selectChild: function(child) { vm.selectedChild(child); }
};
ko.applyBindings(vm);
</script>

但是我的视图模型会变得更复杂,我想我选择了吗?能够做的不仅仅是将单个CSS类添加到单个元素。我真的想在子视图模型上创建一个 isSelected 计算属性,这样我就可以添加依赖于它的其他计算属性。

But my viewmodels are going to get more complex, and I'd like "am I selected?" to be able to do more than just adding a single CSS class to a single element. I really want to make an isSelected computed property on the child viewmodel, so I can then add other computed properties that depend on it.

我试过写关于引用 $ data $ root 的JavaScript - 敲门可能会定义这些变量,并且当它调用我的计算评估函数时它们会在范围内:

I've tried just writing JavaScript that refers to $data and $root, on the off-chance that knockout might define those variables and somehow have them be in scope when it calls my computed evaluator function:

{
  name: 'Bob',
  isSelected: ko.computed(function(){ return $data === $root.selectedChild(); })
}

但没有这样的运气:在我的评估者里面功能 $ data $ root 都是 undefined

But no such luck: inside my evaluator function, both $data and $root are undefined.

我也尝试过使用我的评估者中有 ko.contextFor ,因为它确实可以访问 $ data $根。不幸的是,在我的评估函数中, contextFor 也总是返回 undefined 。 (无论如何,我并没有对这个策略抱有很高的期望 - 如果我不得不像这样追逐它的背后,还不清楚淘汰赛如何能够跟踪依赖关系。)

I've also tried using ko.contextFor inside my evaluator, since it does give access to $data and $root. Unfortunately, inside my evaluator function, contextFor also always returns undefined. (I didn't hold out high hopes for this strategy anyway -- it's not clear how well knockout would be able to track the dependencies if I had to go behind its back like this.)

我总是可以在每个子视图模型上手动设置一个属性,该视图返回到父视图模型。但我知道淘汰赛有能力为我做这件事,我想至少在我自己编写之前探讨是否可以使用它的机制。

I could always manually set a property on each child viewmodel that refers back to the parent viewmodel. But I know that knockout has the ability to do this for me, and I'd like to at least explore whether I can use its mechanisms before I go writing my own.

似乎应该可以将上面的绑定表达式转换为计算的observable - 毕竟,这就是淘汰已经做的

It seems like it should be possible to translate the above binding expression to a computed observable -- after all, that's what knockout already does:


另一个巧妙的技巧是声明性绑定只是作为计算的observable实现。

The other neat trick is that declarative bindings are simply implemented as computed observables.

但是如何处理 $ data $ root 伪变量?

But how do I go about dealing with the $data and $root pseudovariables when I'm writing my own computed observable?

推荐答案

伪变量仅在数据绑定的上下文中可用。理想情况下,视图模型本身不应该知道或者对显示它的视图有任何依赖性。

The pseudovariables are only available in the context of data binding. The view model itself ideally should not know about or have any dependencies on the view that is displaying it.

因此,在视图模型中添加计算的observable时,你没有知道它将如何绑定(就像将要成为$ root)。视图模型或视图模型的一部分甚至可以在不同级别分别绑定到页面的多个区域,因此伪变量将根据您开始的元素而有所不同。

So, when adding computed observables in the view model, you have no knowledge of how it will be bound (like what is going to be $root). A view model or part of a view model could even be bound separately to multiple areas of the page at different levels, so the pseudo-variables would be different depending on the element that you are starting with.

这取决于你想要完成什么,但如果你想要你的孩子有一个 isSelected 计算可观察这表示此项目是否与父视图模型上的选定项目相同,那么您将需要找到一种方法使父项可供子项使用。

It depends on what you are trying to accomplish, but if you want your child to have an isSelected computed observable that indicates whether this item is the same as the selected item on the parent view model, then you will need to find a way to make the parent available to the child.

一个选项是将父级传递给孩子的构造函数。您甚至不需要将指针添加到父项作为子项的属性,并且可以直接在计算的observable中使用它。

One option is to pass the parent into the constructor function of your child. You do not even need to add the pointer to the parent as a property of the child and can just use it in your computed observable directly.

类似于:

var Item = function(name, parent) {
   this.name = ko.observable(name);  
   this.isSelected = ko.computed(function() {
       return this === parent.selectedItem();        
   }, this);
};

var ViewModel = function() {
   this.selectedItem = ko.observable();
   this.items = ko.observableArray([
       new Item("one", this),
       new Item("two", this),
       new Item("three", this)
       ]);
};

此处示例: http://jsfiddle.net/rniemeyer/BuH7N/

如果您关心的是所选状态,那么您可以调整它以通过对子构造函数的 selectedItem observable的引用,如: http://jsfiddle.net / rniemeyer / R5MtC /

If all you care about is the selected status, then you can tweak it to pass a reference to the selectedItem observable to the child constructor like: http://jsfiddle.net/rniemeyer/R5MtC/

如果您的父视图模型存储在全局变量中,那么您可以考虑不将其传递给子项并直接使用它喜欢: http://jsfiddle.net/rniemeyer/3drUL/ 。我更喜欢将引用传递给孩子。

If your parent view model is stored in a global variable, then you could consider not passing it to the child and using it directly like: http://jsfiddle.net/rniemeyer/3drUL/. I prefer to pass the reference to the child though.

这篇关于如何在.computed()observable中使用knockout的$ parent / $ root伪变量?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆