【问题标题】:Ember transition & rendering complete eventEmber 过渡和渲染完成事件
【发布时间】:2013-06-30 11:53:09
【问题描述】:

是否有任何事件触发说明过渡/渲染已完成(并且 dom 可见/准备就绪)。

setupcontroller/activate 在 dom 构建/渲染之前进行

didInsertElement 仅在我已经插入一个元素并且我只是在它下面切换模型时才第一次被触发。

我真正在寻找的是过渡完成事件

我想我可以做到这一点,但我有点希望它已经内置...

Ember.Router.reopen({
  didTransition:function(infos) {
     this._super(infos);
     console.log('transition complete');  
  }
});

更酷的是回调为它完成过渡的路线,我可能不得不写这个并提交一个拉取请求。

【问题讨论】:

  • 看看这个要点gist.github.com/machty/5723945 描述的变化已经在 RC6 中了
  • 是的,我确实看到了。它有部分帮助,唯一的问题是我可以在转换后运行代码,但这仍然不是在它被插入到 dom 之后。

标签: javascript ember.js promise transitions


【解决方案1】:

有几种不同的方法可以解决这个问题

didInsertElement

第一次插入视图时会触发,但如果模型在视图下切换出去则不会触发(因为 Ember 喜欢重用项目,因为它比重建整个 DOM 便宜)。下面的例子。

简单

如果只需要做一次,第一次插入视图,使用didInsertElement

App.FooView = Em.View.extend({
  setupSomething: function(){
    console.log('the dom is in place, manipulate');
  }.on('didInsertElement')
});

示例:http://emberjs.jsbin.com/wuxemo/1/edit

复杂

如果您需要在从路由本身渲染 DOM 之后安排一些事情,您可以使用 schedule 并将其插入到 afterRender 队列中。

App.FooRoute = Em.Route.extend({
  setupController: function(controller, model){
    this._super('controller', model);
    Ember.run.schedule('afterRender', this, function () {
      //Do it here
    });
  }
});

示例:http://emberjs.jsbin.com/wuxemo/2/edit

过渡承诺

过渡的承诺将在完成渲染项目之前完成。但它会在完成获取所有模型和控制器并将它们连接起来时为您提供一个挂钩。

如果你想连接到过渡事件,你可以这样做:

var self = this;
transitionTo('foo').then(function(){
    Ember.run.schedule('afterRender', self, function () {
          //Do it here
    });
})

【讨论】:

  • 仅供参考:将匿名函数传递给scheduleOnce 不会安排它“一次”,因为它正在检查函数引用以查看它是否已经安排。你需要在某个静态的地方(比如在对象上)定义函数,所以它是:Ember.run.scheduleOnce('afterRender', this, this.myStaticFunction)
  • 是的,很好,在我写的时候我没有意识到这一点,并且在我的答案中没有做足够的清理工作。好点,并且更新到不会给人错误的印象。去抖动和节流也是如此(并且经常被误解)
  • 组件可以监听renderComplete事件吗?
【解决方案2】:

didTransition 确实如您所愿 - 但它是一个动作而不是一个钩子

XXRouter
actions: {
    didTransition: function() {
        this.controller.set("hasTransitioned", true); // or whatever is needed?!
        return true; // Bubble the didTransition event
    },
}


XXController    
observeTransition: function() {
    alert('complete Transition');
}.observes('hasTransitioned'),

【讨论】:

    【解决方案3】:

    afterModel 钩子可能对你有用:

    App.MyRoute = Ember.Route.extend({
      afterModel: function(model, transition) {
        transition.then(function() {
          // Done transitioning
        });
      }
    });
    

    我使用 RC-7 对有和没有动态路段的路线(即有模型的路线和没有模型的路线)进行了测试。无论哪种方式,它似乎都有效。

    请参阅此 JSBin 以获取 RC-6 示例:
    输出:http://jsbin.com/OteC/1/
    来源:http://jsbin.com/OteC/1/edit?html,js

    【讨论】:

    • 这个promise resolve最适合知道转换完成了。非常适合在视图中调用控制器属性并知道您拥有正确的模型。
    • 谢谢,正是我需要的。在 Ember 1.7.0 中运行良好。
    • 我现在可以吻你。我的 afterModel 正在对父控制器进行模型更改,但模板没有更新新数据。我将更改移至过渡。然后一切都变得更好了。
    • 据我所知,在最新的 Ember 中不起作用。如果在 afterModel() 中,你尝试访问路由器模板中不存在的 DOM 元素
    【解决方案4】:

    setupController 是路由器在完成转换之前调用的最后一件事。如果它没有错误地完成,就 Ember 而言,过渡就完成了。通过启用LOG_TRANSITIONS_INTERNAL,您实际上可以看到这一点。

    此时,无论控制器是否抛出错误,视图是否抛出错误等都无关紧要。路由器已完成转换到目标路由。

    所以setupController 是与didTransition 对应的Router 的最后一个位置。

    当支持控制器的内容/模型在现有视图上发生更改时,绑定就会启动。此时发生在视图上的大多数更改都是通过变形。

    我能想到的最接近的地方是View.render,它将更改推送到RenderBuffer。但是您仍然需要考虑这里发生的通过 mixins 进行的变形。

    【讨论】:

    • 为了迂腐,我会说“setupController 是路由器在完成转换后调用的第一件事”,尽管我认为这取决于您分配给单词“finalize”的精确语义"。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-10
    • 2017-03-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多