与KnockoutJS的组件间通信

时间:2014-09-10 07:17:57

标签: knockout.js knockout-components knockout-postbox

假设您有一个包含以下视图模型的产品概述页面:

  • ProductIndexViewModel ;绑定到整个页面的根视图模型
    • ProductListViewModel ;用于显示所有产品的小部件
    • ProductRegistrationViewModel ;用于注册新产品的小部件

使用自定义HTML元素(例如<product-list></product-list><product-registration></product-registration>)加载小部件。这很棒,因为我不必在我的根模型中提供这些小部件的任何知识。但是,我还希望在用户注册新产品后刷新产品列表。简而言之:

如何从ProductRegistrationViewModel向ProductListViewModel发送信号?

我已经调查了Knockout Postbox,但这似乎无法解决问题。如果我有多个产品列表并且我只想刷新其中一个,该怎么办?理想情况下,我想在我的组件的视图模型上实现一系列公共方法。然后将两者从我的页面的根视图模型中绑定在一起,如下所示:

var ProductIndexViewModel = function() 
{
    var productRegistrationComponent = ??;
    var productListComponent = ??;

    productRegistrationComponent.onRegistrationComplete(function() {
      productListComponent.refresh();
    };
}

但是,我无法从此处访问这些视图模型。或者我呢?

如何从我的根视图模型访问子视图模型?

最后,如果有人看到我问题的更好解决方案:我全都耳朵!

2 个答案:

答案 0 :(得分:2)

听起来他们应该共享一个可观察的数组(产品列表)。我认为最好在根模型中定义此列表并将其传递给依赖于它的小部件。如果两个组件共享相同的observable,则不必担心两个组件之间的通信。 您的HTML可能如下所示:<product-list data-bind="list: $root.allProducts"></product-list>

如何从我的根视图模型访问子视图模型?

如果您愿意,可以使用ko.contextFor获取HTML元素的上下文。

答案 1 :(得分:1)

我刚刚做了这样的事情。在我的方法中,我的组件创建了一个API对象,该对象被分配给由父组件传入的observable。例如,我有一个由组件包装的数据表,我希望能够找到所选的行:

pageModel = function() {
  this.dtAPI = ko.observable();
}

ko.applyBindigns(new pageModel());
<datatable params="api: dtAPI, data: getTableData()"></datatable>

在组件内部,您可以将observable设置为对组件的API的引用,以便其他人可以调用对它的调用。就我而言,我并不完全是这种情况,我将API暴露给数据绑定,以便我可以稍后操作数据绑定元素(在这种情况下,它是一个数据表绑定:

if (binding.api != null)
{
    // expose datatable API to context's api binding.
    binding.api({
        getSelectedData: function() { return _getSelectedData(element);}
    });
}

然后在main(父)组件中,您可以执行以下操作:

dtAPI.getSelectedData();

到目前为止,我发现这种模式是一种从内部组件中公开行为的方法。