如何在.computed()observable中使用knockout的$ parent/$ root伪变量?

Joe*_*ite 59 javascript knockout.js

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

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

<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>
Run Code Online (Sandbox Code Playgroud)

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

我尝试过只编写引用的JavaScript,$data并且$root,当敲门可能定义这些变量并且以某种方式让它们在调用我的赋值computed函数时它们在范围内时:

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

但没有这样的运气:我的评估中function,无论是$data$rootundefined.

我也尝试ko.contextFor在我的评估器中使用,因为它确实提供了访问$data$root.不幸的是,在我的评估函数中,contextFor也总是返回undefined.(无论如何,我对这个策略并没有寄予厚望 - 如果我不得不像这样追逐它,那么目前还不清楚淘汰赛如何能够跟踪依赖关系.)

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

看起来应该可以将上面的绑定表达式转换为计算的observable - 毕竟,这就是淘汰赛已经做到的:

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

但是当我编写自己的计算可观察量时,如何处理$data$root伪变量?

RP *_*yer 77

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

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

这取决于你想要完成什么,但如果你想让你的孩子有一个isSelected计算的observable来指示这个项目是否与父视图模型上的选定项目相同,那么你需要找到一种方法来制作父母可以为孩子服务.

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

就像是:

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)
       ]);
};
Run Code Online (Sandbox Code Playgroud)

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

如果您关心的只是所选状态,那么您可以调整它以将对selectedItemobservable 的引用传递给子构造函数,如:http://jsfiddle.net/rniemeyer/R5MtC/

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