【问题标题】:Knockout nested components: $(document).ready() ... runs before nest component is loaded淘汰嵌套组件: $(document).ready() ... 在嵌套组件加载之前运行
【发布时间】:2015-12-21 10:05:51
【问题描述】:

所以我有几个嵌套的剔除组件:

<component1>
   <component2>
   ....
   </component2>
</component1>

component1 是我自己编写的组件,但 component2 是第三方代码,我不应该更改它。问题来了:

$(document).ready() 中,为了简单起见,我使用jquery $('button').click(...) 将点击事件处理程序分配给所有按钮。结果就是,只有组件 1 和组件 2 外的按钮获得处理程序,组件 2 内的按钮都没有处理程序(当我单击它们时没有任何反应)。

请注意,component2 依赖(消耗)来自某些 ajax 调用的数据,因此这可能会延迟其加载。因为 ajax 是异步的,所以 $(document).ready() 可能在 ajax 完成之前运行,因此,$('button').click(...) 没有捕获组件内部的按钮,因为它们还没有被渲染。

其他问题: component1 的 viewmodel1 在 component2 中时似乎总是为空。上下文是正确的;它只是空的(例如:viewmodel1的数组在component2内部为空,在component2之外不为空。

如何让component2里面的所有按钮都得到handler?

【问题讨论】:

    标签: javascript jquery ajax knockout.js


    【解决方案1】:

    如果您无法修改 component2 并且它没有为您提供知道何时完成加载的方法,那么您唯一的选择就是循环直到它完成加载。您可以通过测试您知道组件内的某些类/id/等来判断它何时完成加载。

    <component1>
       <component2>
           ...
           <div class="some-class-I-know-will-be-here"></div>
       </component2>
    </component1>
    
    var loop = window.setInterval(function () {
        if ($('.some-class-I-know-will-be-here')[0]) {
            componentHasLoaded();
            window.clearInterval(loop);
        }
    }, 100);
    

    请注意,这确实是一种破解/解决方法。您可能应该将“onClick”函数传递给组件,该组件将适当地连接它。

    [编辑]

    这种解决方法对于简单地附加点击事件来说太过分了。其他答案涵盖了如何使用 jQuery 的事件委托来实现这一点。只有在创建组件后需要修改组件的模板/viewModel 并且您无法以任何其他方式修改组件时,此解决方法才实用。

    【讨论】:

    • 谢谢。至于合适的方法,如何将“onClick”函数传递给component2?
    • Component2 必须修改以接受它作为参数。然后它会在适当的时候调用它。
    • 我明白了。由于我无法修改 Component2,我将坚持使用循环。非常感谢。
    【解决方案2】:

    您应该使用event delegation,以便在您设置触发器时不必存在 DOM 元素。

    $(document).on('click', 'button', ...);
    

    【讨论】:

      【解决方案3】:

      尝试使用 jQuery 功能将事件处理程序添加到内部的任何未来元素。检查下面代码的语法。

      $(document).on("click", "div", function(){
          console.log(this.id);
      });
      

      即使某些 div 尚未加载,点击事件也会对这些元素起作用。

      【讨论】:

        【解决方案4】:

        如果 jQuery 委托事件不适合您的场景并且您使用的是 Knockout >= 3.5.0,则您可以在组件上使用 childrenComplete 绑定参数。

        我是这样用的:

        <script>
                window.componentReady= false;
                function onAccordionReady() {
                    window.componentReady = true;
                }
        </script>
        <div data-bind="component: {name: 'my-component', childrenComplete: onComponentReady">
        </div>
        

        在 javascript 上,类似于 CrimsonChris 的回答,但性能可能更高:

        <script>
        $(document).ready(function documentReady() { //Notice the named function
        
            if (!window.componentLoaded) {
                setTimeout(documentReady, 1000);
                return; //Don't forget the return!
            }
        
            //... All the code I want to execute on document ready that
            //dependent on the components having finished rendering
        
        }
        </script>
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-03-08
          • 2017-12-31
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多