2016-03-10 62 views
3

我遇到了knockout.js组件和require.js。 到目前为止,这工作得很好,但我正在努力处理以下问题。从其包含viewmodel访问组件viewmodel

比方说,我有我的组件的一个实例在一个非常简单的HTML页面:

<div id="exams"> 
    <databound-exam-control></databound-exam-control> 
</div> 

从包含视图模型:

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()); 
}); 

我想获得孩子视图模型内容后当我点击一个按钮时保存页面的所有数据。

现在我只是想显示显示在标签的父/子的ViewModels:

<div> 
    <pre data-bind="text: childViewModel()"></pre> 
</div> 

随着包含视图模型的帮助:

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

我得到的调用ko.dataFor在下面的错误,可能是因为该网页无法完全呈现:

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

是不是这样?或者我在这里完整地忽略了这一点?

任何帮助表示赞赏。

+0

我想说,设置你的主视图模型来跟踪你创建的子模型可能会更好。作为一个人为的例子,你可以看看:https://jsfiddle.net/timh06/91n3m25t/ 也可以不用'ko.dataFor'来查看'ko.contextFor',它应该可以访问绑定元素的上下文。 – Timh

回答

3

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

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

现在,父组件可以使用childViewModel可观察值访问子视图模型。

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

  • 在父创建一个寄存器API的回调,像这样:registerApi = function(api) { config.childApi = api }
  • 通这个作为参数传递给在子视图模型构造器子组件
  • 调用回调传递孩子API

这样,我可以通过存取权限的子组件这样显示的API:config.childApi.aMethosExposedByTheChild()

IMPO rtant注意:您必须考虑到,由于子组件异步加载,子项公开的信息不能直接使用。除非您需要立即使用它,否则这不是问题。例如,就你而言,它看起来像是在组件加载并且用户与它进行交互之后从子视图模型获得信息,所以这不是问题。如果您需要尽快访问它,则可以使用轮询或更好地向子项公开延期(示例实现:$.Deferred),以便它可以解决此问题,让母公司模型知道它已经可用。当子视图模型依赖通过AJAX调用加载外部资源(例如加载下拉列表或服务器上存在的其他信息)时,也会发生这种情况。

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

+0

感谢您的详细解答,我会尽力回复您。我也尝试使用[knockout-postbox](https://github.com/rniemeyer/knockout-postbox)。 –