ember.js路由渲染:使用setTimeout()进行dom操作?

ember.js路由渲染:使用setTimeout()进行dom操作?,dom,ember.js,router,Dom,Ember.js,Router,如果我想在视图呈现后调用jquery插件(例如,将一个表插入dom),除了使用window.setTimeout()执行此操作之外,还有其他可能性吗 此代码执行此任务(1ms超时;这很奇怪): 但是这个代码不起作用: Route.HomeRoute = Ember.Route.extend({ renderTemplate: function() { this.render("home"); // render the home view

如果我想在视图呈现后调用jquery插件(例如,将一个表插入dom),除了使用window.setTimeout()执行此操作之外,还有其他可能性吗

此代码执行此任务(1ms超时;这很奇怪):

但是这个代码不起作用:

Route.HomeRoute = Ember.Route.extend({
        renderTemplate: function() {

            this.render("home");   // render the home view

            $(".tables").insertTables();    // this would add a table

        }
    });
我知道有Ember.View.didInsertElement(),但因此我必须在父视图上设置回调,我只是想知道,为什么上面的代码示例不能按预期工作


非常感谢

我不知道我的答案是否100%准确,但我想这就是它的解释:

我想问题是,您认为render()方法是同步完成其工作的。但事实并非如此。相反,它会安排HomeView的渲染。渲染被安排到余烬的运行循环中。在第二个示例中,您的代码计划渲染,然后立即尝试访问其DOM元素(我猜.tables是主模板的一部分)。但此时不渲染视图!第一个示例是有效的,因为涉及1ms超时在此超时期间,Ember RunLoop将启动并开始其魔术。它执行渲染,然后当CPU再次空闲时,可以调用超时函数

实际上,您在这里要做的是:
在成功呈现视图时,在我的DOM上执行一些操作
。这可以在Ember中完成,无需使用setTimeout。下面的代码访问RunLoop并计划在RunLoop结束时执行的函数

Ember.run.next(function() {
     $(".tables").insertTables();    // this would add a table
});
下面是一篇关于RunLoop的文章,如果您想了解Ember的这些细节,了解它很重要: -


最后但并非最不重要的一点:在路由中进行这样的DOM操作非常尴尬。你的路线应该永远是自由的,没有这些东西。元素、选择器和jQuery插件只应在视图层中使用。其他一切似乎都不好。也许你想分享更多关于你为什么选择这种方法的细节?有可能比这个更好的解决方案。

第二个示例不起作用的原因可能是由于
this.render
计划dom插入,以便稍后在当前运行循环中执行

DOM插入是在运行循环结束时完成的,通过使用
setTimeout
,您可以在运行循环结束后调用插件,从而确保模板被注入DOM。(不需要1ms,0ms可能有效)

你可能会说这个运行循环非常复杂,特别是对于一个Ember.js初学者来说。理想情况下,它应该对应用程序开发人员透明。您遇到其副作用的原因是,不应在路由器中处理DOM操作

我的第一反应是告诉您使用
didInsertElement
,或者视图中的任何代码或钩子,因为DOM操作应该在那里发生。但你似乎意识到了这一点,并且出于某种原因无法使用它(我无法确认或否认,因为我没有足够的信息)


我给你的建议是,在
didInsertElement

中尽你最大的努力,我想这是我们第二次在同一时间回答:)看到别人如何解释同一个问题总是很好:-)谢谢,伙计们!运行循环正是我不理解的事情。这就是我“接受”mavilein的答案为正确答案的原因,谢谢那篇文章的链接!我有一些疯狂的架构东西,并清理了它-现在我可以在我过度编写的didInsertElement函数中完成这项工作。但是是的,我的问题是对运行循环的理解。
Ember.run.next(function() {
     $(".tables").insertTables();    // this would add a table
});