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

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

问题描述

knockout.js 绑定表达式中,我可以使用 $data$parent$root 伪变量.当我使用 ko.computed observable 时,如何获得这些伪变量的等效项在 JavaScript 中声明?

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,但有可能淘汰赛可能会定义这些变量并以某种方式将它们放入当它调用我的 computed 评估器函数时的作用域:

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(); })
}

但没有这样的运气:在我的评估器 function 中,$data$root 都是 undefined.

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

我也试过在我的评估器中使用 ko.contextFor,因为它确实可以访问 $data$root.不幸的是,在我的评估器函数中,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.

但是,当我编写自己的计算 observable 时,如何处理 $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 可观察对象的引用传递给子构造函数,例如: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 中使用淘汰赛的 $parent/$root 伪变量?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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