繁体   English   中英

在Ember中,如何创建对另一个组件的操作做出反应的组件?

[英]In Ember, how do I create a component that reacts to the action of another component?

我有一个button-icon组件,当盘旋时,将发送hoverInhoverOut操作(示例代码,所以请原谅任何错误):

应用/组件/按钮图标/ component.js:

export default Ember.Component.extend({
  didInsertElement: function() {
    // hover in
    this.$().hover(function() {
      this.sendAction('hoverIn');
    ,
    // hover out
    function() {
      this.sendAction('hoverOut');
    }
  },

  // more code here to handle other stuff
});

应用/组件/按钮图标/ template.hbs:

<button>{{yield}}</button>

我还有一个button-tooltip组件,当按钮悬停时应显示该组件:

应用/组件/按钮工具提示/ component.js:

export default Ember.Component.extend({
    // some code here to handle positioning
});

应用/组件/按钮工具提示/ template.hbs:

<div>{{yield}}</div>

在我的模板中,我想像这样使用两者:

应用程序/索引/ template.hbs:

{{#button-icon}}
  <div>Cat</div>
  {{#button-tooltip}}<img src="cat.png">{{/button-tooltip}}
{{/button-icon}}

{{#button-icon}}
  <div>Dog</div>
  {{#button-tooltip}}<img src="dog.png">{{/button-tooltip}}
{{/button-icon}}

{{#button-icon}}
  <div>Rat</div>
  {{#button-tooltip}}Nobody wants to see a picture of a rat!{{/button-tooltip}}
{{/button-icon}}

如何让button-iconbutton-tooltip进行通信,以便在图标悬停时显示工具提示? 如果我只有一个按钮,我可以将按钮和工具提示绑定到控制器上的属性,但我有一个变量列表要显示。 我也可以将这两个组件包装在另一个组件中(称为button-with-tooltip或者其他东西),但这似乎已经开始进入组件构建。

当你拥有这些模板时,设置这种交互非常复杂。 您的组件完全独立,但它们应该具有父子连接,因为它们实际上是父组件和子组件。

对我来说更合适的方法如下。

应用程序/索引/ template.hbs

{{#buttons-list buttons=property_with_a_correct_list_from_the_index_controller}}

应用程序/组件/按钮列表/ template.hbs

{{#each button in buttons}}
  {{#button-icon data=button}}
{{/each}}

应用/组件/按钮图标/ template.hbs

<div>{{data.title}}</div>
{{#button-tooltip data=data.tooltip}}

应用/组件/按钮图标/ component.js:

export default Ember.Component.extend({
  tagName: 'button',

  ...

});

应用/组件/按钮工具提示/ template.hbs:

{{#if isPicture}}
  <img src={{data.image}} />
{{else}}
  {{data.text}}
{{/if}}

应用/组件/按钮工具提示/ component.js:

export default Ember.Component.extend({
  tagName: 'div'
  isPicture: function() {
    this.get('data.type') == 'image'
  }.property('data.type')
});

property_with_a_correct_list_from_the_index_controller应如下所示

[
  {title: 'Cat', tooltip: {isPicture: true, image: 'cat.png'}},
  {title: 'Dog', tooltip: {isPicture: true, image: 'dog.png'}},
  {title: 'Rat', tooltip: {isPicture: false, text: 'Nobody wants to see a picture of a rat!'}}
]

我们来看看吧:

  • 我将组件中的edged标签移动到tagName属性中的控制器
  • 工具提示的内容现在由工具提示本身定向,而不是由父图标组件定向
  • 现在工具提示和图标有明确的关系,因此图标最终任何合理的方法来控制它

现在让我们确定您对样本的高级要求:

  • 用户应该在悬停图标时看到工具提示。
  • 留下图标时,用户不应该看到工具提示。

如您所见,图标组件完全控制工具提示可见性。 在这种情况下,我会考虑使用条件模板的方法。 例如:

应用/组件/按钮图标/ component.js:

export default Ember.Component.extend({
  tagName: 'button',
  showTooltip: false,

  didInsertElement: function() {
    self = this // this will be redefined inside of hover function
    // hover in
    this.$().hover(function() {
      self.set('showTooltip', true);
    ,
    // hover out
    function() {
      self.set('showTooltip', false);
    }
  },

  // more code here to handle other stuff
});

应用/组件/按钮图标/ template.hbs

<div>{{data.title}}</div>
{{#if showTooltip}}
  {{#button-tooltip data=data.tooltip}}
{{/if}}

如您所见,您的样本以更清晰的方式重写,您可以在其中看到控制工具提示可见性的方法。 我建议仅在需要控制工具提示可见性时才使用此方法。

回到

这里有更多代码来处理其他内容

为此,我建议不要放弃绑定属性的方法。 只需在button-icon组件中创建一个具有所需状态的属性,并在button-tooltip组件中创建相应的计算属性,该组件将侦听属性中的更改。

例:

应用/组件/按钮图标/ component.js:

export default Ember.Component.extend({
  tagName: 'button',
  tooltipProps: [],

  didInsertElement: function() {
    self = this // this will be redefined inside of hover function
    // hover in
    this.$().hover(function() { 
      self.get('tooltipProps').addObject('showIt');
    , function() { // hover out
      self.get('tooltipProps').removeObject('showIt');
    });
    this.$().on('click', function() {
      self.get('tooltipProps').addObject('makeitRed');
    });
  },

  // more code here to handle other stuff
});

应用/组件/按钮图标/ template.hbs

<div>{{data.title}}</div>
{{#button-tooltip data=data.tooltip props=tooltipProps}

应用/组件/按钮工具提示/ component.js:

export default Ember.Component.extend({
  tagName: 'div'
  isPicture: function() {
    this.get('data.type') == 'image'
  }.property('data.type'),

  onPropsChange: function() {
    if (this.get('props.makeItRed')) {
      // make it actually red directly by the own component code
    }
  }.observe('props') // an observer because you need to do actions here, if you want to change the internal state use a computed property
});

PS但我喜欢的第一种方法更多%)

一旦你使用支持在组件中产生值的ember版本,我认为这是1.10.0,你可以做到以下,这是非常直观的。

{{#button-icon as |active|}}
  <div>Cat</div>

  {{#button-tooltip active=active}}
    <img src="cat.png">
  {{/button-tooltip}}
{{/button-icon}}

在您的button-icon组件中,您可以设置一个值,例如isActive ,然后将其发送下来。

<button>{{yield isActive}}</button>

这个想法是行动起来,数据下降。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM