8

我有一个使用 3.2.0 的嵌套 KnockoutJS 组件的层次结构。它工作得很好,但我希望在加载和渲染整个组件层次结构后执行一些代码。它大致相当于 afterRender(),与 afterRender 相同的常见用例需要。

我已经尝试了一些方法,但到目前为止没有运气:

  1. 在根模板中添加了以下内容,但在加载嵌套组件之前调用它,所以为时过早。 <!--ko template: {afterRender: onLoad.bind($data)} -->
  2. 使用最新的 3.3.0-alpha 并在所有组件上指定 synchronous:true。但我相信,由于我使用的是 AMD,组件仍然是异步“加载”的,这意味着仅仅因为我的根 applyBindings() 返回,并不意味着所有组件都已加载和渲染。
  3. 甚至尝试构建延迟对象的集合,这些对象仅在加载相应组件时才被解析。这变得过于复杂并且由于我不会进入的原因仍然没有工作。

一旦加载和渲染了完整的 knockoutjs 组件层次结构,有没有办法调用回调?谢谢!

我刚刚遇到这两个线程,所以似乎其他人也在寻找这个。与现有解决方法的主要区别在于它们不适用于嵌套组件。

4

3 回答 3

3

我编写了一个敲除库,当所有组件都已加载和绑定时触发一个事件。它使用引用计数,类似于用于垃圾收集的引用计数。我在我的项目中广泛使用组件,包括嵌套很多层次,我不能不知道什么时候一切都“准备就绪”。我没有花太多时间在使用文档上,但基础知识就在那里。

Git Hub 维基: https ://github.com/ericraider33/ko.component.loader/wiki

小提琴: https ://jsfiddle.net/ericeschenbach/487hp5zf/embedded/result/

使用 HTML:

<div id="ko-div">
  Status: <span data-bind="text: loading() ? 'Loading' : 'Done'"></span>
  <br><br>
  <test-panel></test-panel>
</div>

用法 JS:

var pageModel = { 
  loading: ko.observable(true), 
    completedCallback: function (childRef) { 
    pageModel.loading(false); 
    childRef.testValue(childRef.testValue()+1);  
  }
};

var tpRef = ko.componentLoader.ref.child({ completedCallback: pageModel.completedCallback});
var tpModel = { 
  attached: function(element) { return tpRef; },
  testValue: ko.observable(5)
};

ko.components.register('test-panel', {
    viewModel: function() { return tpModel; },
    template: '<div data-bind="attached: true">Test Panel<br>From Code <span data-bind="text: testValue"></span></div>'
});


ko.componentLoader.setOptions({ verbose: true });
ko.applyBindings(pageModel, $('#ko-div')[0]);
于 2016-02-23T16:14:09.117 回答
2

这对我有用。我没有尝试所有可能的变化,例如混合同步和异步组件,或使用自定义组件加载器。

KO 3.3.0 中有一个方法,所有组件加载都经过:

ko.components = { get: function(componentName, callback) { ...

get方法是用期望调用的,componentName并且当组件已加载时 -callback调用 a。

因此,您需要做的就是在每次调用时包装ko.components.getcallback递增,并在执行后递减。当计数达到零时,意味着所有组件都已加载。pendingComponentsCountcallback

25 行 JS 代码(使用 underscorejs)。

您还需要处理没有遇到任何组件的特殊情况,ko.applyBindings这也意味着所有组件(全部为零)都已加载。

同样,不确定这是否适用于所有情况,但它似乎适用于我的情况。我可以想到一些很容易破坏的场景(例如,如果有人ko.components.get在你包装它之前缓存一个引用)。

于 2016-04-01T14:41:05.923 回答
1

如果您正在使用 ko.components 这可能有用:

1)创建一个延迟对象来跟踪每个组件的加载

var statusX = $.Deferred()
var statusY = $.Deferred()

2)通知敲除告诉你组件何时加载并准备好

ko.components.get('x-component', statusX.resolve) //Note: not calling resolve, but passing the function
ko.components.get('y-component', statusY.resolve)

3) 同步两个状态延迟

$.when(statusX.promise(), statusY.promise())
 .done( function allComponentsLoaded(componentX, componentY){ 
            //Both components are ready here 
            //Note the arguments from the function comes via
            //ko->jquery deferred resolve
           });
于 2015-02-13T14:09:31.047 回答