javascript - 如何从 .computed() 可观察对象中使用 knockout 的 $parent/$root 伪变量?

标签 javascript knockout.js

knockout.js 里面绑定(bind)表达式,我可以使用 $data, $parent, and $root pseudovariables .当我使用 ko.computed observable 时,我怎样才能得到这些伪变量的等价物?在 JavaScript 中声明?

我有一个带有子集合的父 View 模型,父 View 模型有一个 selectedChild 可观察对象。鉴于此,我可以使用数据绑定(bind)表达式将 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>

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

我试过只编写引用 $data$root 的 JavaScript,以防 knockout 可能定义这些变量并以某种方式将它们放入它调用我的 computed 评估函数时的作用域:

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

但没有这样的运气:在我的求值器函数中,$data$root 都是未定义

我也试过使用 ko.contextFor在我的求值器中,因为它确实提供了对 $data$root 的访问权限。不幸的是,在我的求值函数中,contextFor 也总是返回 undefined。 (无论如何,我对这个策略并没有抱太大希望——如果我不得不像这样背在它的背后,目前还不清楚 knockout 能够跟踪依赖性的程度。)

我总是可以在每个返回父 View 模型的 subview 模型上手动设置一个属性。但我知道 knockout 有能力为我做这件事,我想至少在我自己写之前探索一下我是否可以使用它的机制。

似乎应该可以将上述绑定(bind)表达式转换为计算可观察对象——毕竟,that's what knockout already does :

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

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

最佳答案

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

因此,当在 View 模型中添加计算的可观察对象时,您不知道它将如何绑定(bind)(比如 $root 是什么)。 View 模型或 View 模型的一部分甚至可以在不同级别分别绑定(bind)到页面的多个区域,因此伪变量会根据您开始使用的元素而有所不同。

这取决于您要完成的任务,但是如果您希望您的 child 有一个 isSelected 计算可观察对象来指示该项目是否与父 View 模型中的选定项目相同,那么您将需要找到一种方法让 child 可以使用 parent 。

一种选择是将父级传递给子级的构造函数。您甚至不需要将指向父级的指针作为子级的属性添加,只需在计算的可观察量中直接使用它即可。

类似于:

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/

如果您的父 View 模型存储在全局变量中,那么您可以考虑不将其传递给 subview 模型并直接使用它,例如:http://jsfiddle.net/rniemeyer/3drUL/ .不过,我更愿意将引用传递给 child 。

关于javascript - 如何从 .computed() 可观察对象中使用 knockout 的 $parent/$root 伪变量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8640748/

相关文章:

javascript - 在编写Chrome扩展时, "var i in windows"(在回调函数(windows)内)是如何编译的?

jquery - 在一个使用带有多个 ViewModel 的 knockout.js 的程序中,如何知道一个特定的 View 模型会因属性的变化而改变?

knockout.js - KnockOut 映射分层 JS 对象

javascript - 无法弄清楚为什么参数在 JS fibonacci 函数的递归过程中发生变化

javascript - 模态内的表单输入不可点击

javascript - 用于加载的弹出窗口在 knockout 中不起作用

javascript - 删除 Knockout.js 中动态创建的行

javascript - 无法读取外部 viewmodel.js 中未定义的属性 'fromJS'

javascript - 数字类型输入的onkeyup vs onchange

javascript - 无法读取未定义的属性 'x' (JavaScript)