从另一个组件访问组件的数据

时间:2018-01-22 23:22:22

标签: knockout.js knockout-2.0 knockout-3.0

我想获得' first-component'的viewModel来自' second-component'并为两个组件同步self.prop。我使用Knockout库。这是我的代码:

ko.components.register('first-component', {
    template: '<strong><span data-bind="text: prop"></span></strong>',
    viewModel: function(params){
        var self = this;

        self.prop = ko.observable(params.initialText);
    }
});

ko.components.register('second-component', {
template: '<div><input type="text" data-bind="value: prop">' 
          + '<button data-bind="click: foo">Click Me</button></div>',
viewModel: function(params){
        var self = this;

        self.prop = ko.observable(params.initialText);
        self.foo = function(){
        // HELP ME! I want to get viewModel of 'first-component' and 
        // synchronize self.prop for both components
            if(ko.components.isRegistered("first-component")){
            //...???

            }
        }
    }
});

在标记中使用组件:

<first-component params="initialText: 'Some text...'"></first-component>

<second-component params="initialText: 'Another text...'"></second-component>

1 个答案:

答案 0 :(得分:1)

为了促进组件和外部视图模型之间的交互,我发现最好的方法是传入一个observable作为参数来管理数据的同步。我使用上面的代码设置了JSFiddle example

第一个更改是创建父视图模型以包含组件之间的共享状态

var parentViewModel {
  sharedText: ko.observable('shared text')
}

然后使用共享文本作为组件的参数。对于第一个组件,initialText设置为sharedText,而第二个组件sharedText则作为第二个参数传入。这是因为共享文本仅在&#34; Click Me&#34;单击按钮。如果sharedText observable都设置为initialText,则更新将自动进行。有时这是必需的,有时不是。

<first-component params="initialText: sharedText"></first-component>
<second-component params="initialText: 'Initial value', sharedText: sharedText"></second-component>

然后在第一个组件中分配属性时,请使用params.initialText中的引用,而不是创建新的observable。当knockout绑定HTML时,它将绑定到parentViewModel.sharedText并随时更新parentViewModel.sharedText时自动更新HTML。

ko.components.register('first-component', {
    template: '<strong><span data-bind="text: prop"></span></strong>', 
viewModel: function(params){
        var self = this;
        self.prop = params.initialText;
    }
});

在第二个组件中,使用初始文本创建新的observable,foo点击处理程序使用params.sharedText中的值更新self.props引用。

ko.components.register('second-component', {
    template: '<div><input type="text" data-bind="value: prop">' 
      + '<button data-bind="click: foo">Click Me</button></div>',
    viewModel: function(params){
        var self = this;
        self.prop = ko.observable(params.initialText);
        self.foo = function(){
            params.sharedText(self.prop());
        }
    }
});

这与在React组件中提取状态非常相似,其中组件在一组属性中传递,包括来自父组件的一组回调,并且回调负责更新共享视图模型。 / p>

我还添加了第三个组件,因为正确处理组件非常重要。有关详细信息,请参阅组件文档中的Disposal and memory management。第三个组件是一个计数器,用于跟踪sharedText已更新的次数。它在knockout observable上使用订阅,如果组件从DOM中删除,那么它需要处理订阅。如果在组件上定义dispose函数,则当从DOM中删除组件时,knockout将自动调用此方法。

ko.components.register('third-component', {
    template: '<div>Counter:&nbsp;<span data-bind="text: count"></span></div>',
  viewModel: function (params) {
     var self = this;
     self.count = ko.observable(0);
     self.sub = params.sharedText.subscribe(function () {
        self.count(self.count() + 1);
     });
     self.dispose = function () {
            self.sub.dispose();
     }
  }
});