淘汰组件更新未被父视图模型订阅的可观察对象
Knockout component updating observable not being subscribed to by parent view model?
我编写了一个名为Upload
的组件,它允许用户上传文件,然后使用这些文件的JSON对象报告。在这个例子中,Upload
组件有一个来自父视图模型的参数:
<upload params="dropzoneId: 'uploadFilesDropzone', postLocation: '/create/upload', uploadedFiles: uploadedFiles"></upload>
最重要的是uploadedFiles
。这里的参数绑定意味着我可以在组件上引用params.uploadedFiles
,并在上传.push()
新对象时引用它们。传递的数据,也称为uploadedFiles
,是父视图模型上的observableArray:
var UploadViewModel = function () {
// Files ready to be submitted to the queue.
self.uploadedFiles = ko.observableArray([]);
};
我确实可以确认在我的组件上,params.uploadedFiles
是一个observableArray,因为它有一个push方法。在组件上修改了这个值之后,我可以console.log()
它看到它实际上已经改变了:
params.uploadedFiles.push(object);
console.log(params.uploadedFiles().length); // was 0, now returns 1
问题是这个变化似乎没有反映在我的父视图模型上。self.uploadedFiles()
不改变,仍然报告长度为0。
无论我是否在父视图模型中添加self.uploadedFiles.subscribe(function(newValue) {});
订阅
无论我是否在我的组件中添加了params.uploadedFiles.valueHasMutated()
方法
我如何从我的组件数组的变化反映在我的父视图模型上的数组?
当源已经是一个时,为什么要创建一个新的可观察数组?您不能期望新对象具有与另一个对象相同的引用:只需将其传递给组件viewModel作为this.uploads = params.uploads
。在下面的示例精简版本中,您将看到单击Add按钮时,两个数组(在不同上下文中引用的同一个数组)保持同步。
ko.components.register('upload', {
viewModel: function(params) {
this.uploads = params.uploads;
this.addUpload = function() { this.uploads.push('item'); }.bind(this);
},
template: [
'<div><button type="button" data-bind="click: addUpload">Add upload</button>',
'<span data-bind="text: uploads().length + '' - '' + $root.uploads().length"></span></div>'].join('')
});
var app = {
uploads: ko.observableArray([])
};
ko.applyBindings(app);
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<div data-bind="component: {name: 'upload', params: {uploads: uploads}}"></div>
只有在你的源数组不可观察的情况下,事情才会变得更复杂,你需要手动订阅来更新源,例如。您将在viewModel中插入以下内容:
this.uploads.subscribe(function(newValue) { params.uploads = newValue; });
另外,text
绑定中的输出不会为源更新,因为它不是可观察的。如果出于某种我无法想象的原因你想要有两个不同的可观测射线(一个源)1组件),您应该仍然能够使用上面的行,但将功能代码替换为params.uploads(newValue)
问题可能与此bug有关(有待确认):https://github.com/knockout/knockout/issues/1863
编辑1:所以这不是一个bug。你必须打开原始参数才能访问原始的可观察对象。在您的例子中,它将是:params.$raw.uploadedFiles() //this would give you access to the original observableArray and from there, you can "push", "remove", etc.
问题是,当你传递一个参数给组件时,它被包装在一个计算的可观察对象中,当你打开它时,你没有原始的observableArray。
参考:http://knockoutjs.com/documentation/component-custom-elements.html advanced-accessing-raw-parameters
While绑定涉及父->子关系的属性以这种方式使用绑定
如果要将数据绑定到子属性data-bind='BindingName: ParentViewmodel.ChildViewModel.ObservableProperty'
这里似乎你想订阅一个函数当任何数据被推入数组时,你可以在可观察数组的长度上写订阅,这可以帮助你捕获你想要的事件。
- 将js对象更改为使用嵌套的可观察数组敲除js视图模型
- $scope$观察数组中的一个特定对象——Angular JS控制器
- 无法观察Ember.js中的对象数组
- 如何从具有动态可观察属性的淘汰对象中获取 JSON 字符串
- 培根.js Bus.plug: 未捕获 错误: 不是可观察的 : [对象对象]
- 使用rxjs创建一个可观察的对象,该对象稍后将连接到web套接字
- 将$scope对象作为参数提供给$digest中的观察者背后的逻辑
- Knockoutjs当父对象's可观察到的变化
- 在ko.applyBindings(..)中执行Knockout js订阅函数(用于可观察对象)
- 聚合物通过父对象观察子属性
- Knockoutjs观察嵌套对象并订阅更改
- Knockout.js用单个json对象绑定一个可观察对象
- 使用AngularJS观察整个对象(深度观察)
- 无限循环当观察父对象时,观察者不更新任何值
- 向KO传递在对象内可观察到的计算值
- 根据某些条件将 JS 绑定到可观察对象内的数组元素
- 如何从下拉列表中由可观察数组填充的选定项中检索完整对象
- 如何创建挖空可观察数组/对象的深层副本
- 对象.观察顺序
- 对象.观察同步回调