从包含其中的viewmodel访问组件视图模型

Oli*_*ROT 4 javascript web-component requirejs knockout.js

我正在使用knockout.js组件和require.js.这到目前为止运作良好,但我正在努力解决以下问题.

假设我在一个非常简单的html页面中有一个我的组件实例:

<div id="exams">
    <databound-exam-control></databound-exam-control>
</div>
Run Code Online (Sandbox Code Playgroud)

从包含viewmodel:

require(['knockout', 'viewModel', 'domReady!'], function (ko, viewModel) {
    ko.components.register('databound-exam-control', {
        viewModel: { require: 'databound-exam-control-viewmodel' },
        template: { require: 'text!databound-exam-control-view.html' }
    });

    ko.applyBindings(new viewModel());
});
Run Code Online (Sandbox Code Playgroud)

我希望获得子视图模型内容,以便稍后在单击按钮时保存页面的所有数据.

现在我只想在pre标签中显示父/子视图模型的显示:

<div>
    <pre data-bind="text: childViewModel()"></pre>
</div>
Run Code Online (Sandbox Code Playgroud)

在包含viewmodel的帮助下:

function childViewModel() {
        var model = ko.dataFor($('databound-exam-control').get(0).firstChild);
        return ko.toJSON(model, null, 2);
};
Run Code Online (Sandbox Code Playgroud)

在调用ko.dataFor期间出现以下错误,可能是因为页面未完全呈现:

除非指定"写入"选项,否则无法将值写入ko.computed.如果要读取当前值,请不要传递任何参数.

是吗?或者我完全错过了这里的观点?

任何帮助赞赏.

Jot*_*aBe 5

在父视图模型和子组件之间进行通信的更简单方法是使用参数.

  • 在父视图模型中创建一个新的可观察属性,如 childViewModel = ko.observable()
  • 将它作为参数传递给子组件<databound-exam-control params= "{modelForParent: childViewModel}">请注意,子modelForParent视图模型中的参数将被称为,并且在父视图模型中将被称为childViewModel
  • 在组件的viewmodel构造函数中,在databound-exam-control-viewmodel.js脚本中,您将接收参数作为构造函数的唯一参数.因此,如果您的构造函数如下所示: function SomeComponentViewModel(params)您可以访问参数asparams.modelForParent
  • 使用该参数将您需要的任何信息从子组件传递到父组件,例如:params.modelForParent(createdChildViewModel).

现在,父组件可以使用childViewModelobservable访问子视图模型.

使用可观察量只是一种可能性.你可以用其他方式做到这一点.例如,将回调作为参数传递,并在viewmodel构造函数中执行该回调,以返回您想要的任何内容.我有时会使用这种模式:

  • 在父级中创建一个寄存器api回调,如下所示: registerApi = function(api) { config.childApi = api }
  • 将此参数作为参数传递给子组件
  • 在子视图模型构造函数中调用传递子API的回调

通过这种方式,我可以访问子组件公开的api,如下所示: config.childApi.aMethosExposedByTheChild()

重要说明:您必须考虑到,当子组件异步加载时,子项公开的信息不会立即可用.

除非您需要立即使用它,否则这不是问题.例如,在您的情况下,看起来您将在加载组件并且用户与其进行交互之后从子视图模型获取信息,因此这不是问题.

如果你需要尽快访问它,你可以使用轮询---或者更好,将延迟(一个示例实现:$ .Deferred)暴露给孩子,这样它就可以解析它让父母veiw模型知道它已经可用.当子视图模型依赖于通过AJAX调用加载外部资源时(例如,加载下拉列表或服务器上存在的某些其他信息),也会发生这种情况.

另一个我不喜欢的选项是父视图模型包含整个子视图模型并将其作为参数传递,因此父视图模型可以完全控制子视图模型.显然,此解决方案不允许组件对其自己的视图模型负责,因此父视图模型和子组件之间存在紧密耦合,这是不可取的.