我有一个 knockout 组件,看起来像这样:
define(['knockout', 'text!./my-component.html', 'pubsub'], function(ko, htmlString, pubsub) {
function viewModel(params) { }
return {
viewModel: {
createViewModel: function(params, componentInfo) {
var vm = new viewModel(params);
pubsub('updateViewModel').subscribe(function(){
// update vm
});
return vm;
}
},
template: htmlString
};
});
我使用 createViewModel
函数订阅更新事件,稍后我将使用该事件来触发其他组件对组件 View 模型的更新。
我将组件包含在我的页面上,如下所示:
<!-- ko component: "my-component" -->
<!-- /ko -->
我想要验证的是事物的加载顺序。我想确保在触发事件之前已调用 createViewModel
。
这是我当前的调用顺序:
// register my-component here
ko.applyBindings(myMainViewModel);
// code that might trigger the component update event here
我读到 ko.applyBindings
是同步的。但这是否还包括对所有已注册组件的隐式 applybindings
,如上面的 my-component
?我是否需要将组件上的 synchronous
属性设置为 true
才能实现此目的?如果我理解正确的话,该标志仅与渲染相关。
我想避免的是在订阅更新事件之前触发更新事件的竞争条件。
最佳答案
如果在调用之前满足以下条件,ko.applyBindings 可以同步 Action :
- 所有组件均已注册
- 所有组件 View 模型都加载到内存中(从网络获取......)
- 所有组件模板均加载到内存中
当组件 View 模型和模板不在内存中时,applyBindings 就会变为异步(如果设置 synchronous=true,则会发生事件)。
此同步标志在 component binding 的 applyBindings 中发挥作用。 。请注意,组件绑定(bind)执行 ko.components.get
调用并传递一个回调,该回调将在 DOM 上呈现组件。
knockout/src/components/loaderRegistry.js具有 ko.components.get 的定义。同步标志表示,如果组件已经缓存(在内存中),则不要放弃对线程的控制。只有当您释放对线程的控制(setTimeout、DOM 插入/等待等)时,applyBindings 才会返回。
我唯一不太确定的是 RequireJS 将如何在这里交互。 Knockout 中有代码会尝试首先使用 require 来解析组件。
无论如何,以下步骤将使您更接近(不完美。请参阅下面的注释)
//Load component vm, template and register it with synchronous=true
ko.appplyBinding(....)
ko.components.get("my-component" , function() {
//trigger component update event
})
这几乎没有什么问题,而且所有问题都有解决方案。
需要等待多个组件完成加载
[要解决这个问题,您可以为每个组件创建一个 Promise 数组,并通过 ko.components.get 解析每个组件。最后你可以 $.when(mypromiseArray, myCallback) 来同步所有的 Promise]
ko.component.get 不会告诉您组件何时最终呈现在 DOM 上。
这是一个更具挑战性的问题。如果您需要这种精度(您需要在 50 毫秒内知道组件何时加载并在 UI 上呈现),我将分享解决方案。
关于javascript - 同步组件注册,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35392138/