理解和使用Ember组件生命周期钩子

时间:2015-10-12 09:49:33

标签: ember.js

我试图弄清楚为什么Ember组件不起作用(并试图了解过程中的组件生命周期)。有问题的组件是Ember-cli-mapbox。它使用嵌套组件。您可以拥有mapbox-map组件,在该组件中,您可以拥有多个mapbox-marker组件。现在,它应该如何工作,mapbox-map组件初始化地图,然后将块传递给子标记组件。子标记组件然后引用传递给它们的映射。正在使用的组件示例(来自组件文档):

{{#mapbox-map mapId='ember-cli-mapbox.7c3914f2' as |map|}}
  {{#each positions as |position|}}
    {{mapbox-marker map=map coordinates=position.coordinates}}
  {{/each}}
{{/mapbox-map}}

现在,使用didInsertElement钩子设置组件,这对我来说很有意义,因为在mapbox-map组件可以绑定到dom中的元素之前,DOM需要到位。虽然它不像那样工作。子组件的didInsertElement在父组件中的didInsertElement挂钩之前执行。因此,标记会在创建之前尝试引用地图。我通过将console.log s放在组件初始化代码中来解决这个问题。我找不到很多关于组件生命周期的文档。 API文档here中引用了didInsertElement,但似乎最新的API文档实际上已过时,并且未引用一堆描述为here的其他挂钩。后一个链接表示生命周期事件按以下顺序发生:

didInitAttrs
didReceiveAttrs
willRender
didInsertElement
didRender

现在,事情变得奇怪了。当我用didInsertElement替换组件中的didInitAttrs时,它会以正确的顺序触发。父组件上的didInitAttrs挂钩首先触发,然后是子组件didInitAttrs挂钩。问题是,DOM还没有准备好,所以它没有多大帮助。我也不能将地图绑定事件放在Ember runloop中,因为它需要返回并作为块传递给子元素。

所以,我的问题是:

  1. 为什么在组件上使用didInsertElement时,钩子会按照它们的顺序执行吗? (孩子,然后是父母)
  2. 这个组件是如何以当前编写的方式工作的?
  3. 如果在官方API文档中没有提及,我是否应该使用上面提到的钩子?
  4. 我在Ember Twiddle here中重新创建了插件。子钩子在父钩子之前被调用,导致组件断开,因为在调用钩子时map未定义。这发生在Ember 1.13.8以及1.13.9。

1 个答案:

答案 0 :(得分:4)

  

为什么在组件上使用didInsertElement时,请执行钩子get   按照他们的顺序执行? (孩子,然后是父母)

1.8版本已更改。它是以前的父母,然后是孩子,但这通常要求人们使用一些复杂的方法等待孩子渲染来做某些事情。改变顺序使学习Ember更简单。

有关详细信息,请参阅https://github.com/emberjs/ember.js/issues/5631

  

这个组件是如何以当前编写的方式工作的?

我没有使用过此插件,也不知道它是否有效。然而,我修复了你的工作:http://ember-twiddle.com/4c3e55d0a66ead378bdf

  

如果他们不是,我应该使用上面提到的钩子   官方API文档中提到了什么?

没有提到这些钩子,因为文档仍在追赶Ember的变化。如果您愿意,请随意使用它们。