[英]In Ember, how do I create a component that reacts to the action of another component?
I have a button-icon
component that, when hovered over, will send a hoverIn
and hoverOut
action (example code so please forgive any errors): 我有一个
button-icon
组件,当盘旋时,将发送hoverIn
和hoverOut
操作(示例代码,所以请原谅任何错误):
app/components/button-icon/component.js:
应用/组件/按钮图标/ 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
});
app/components/button-icon/template.hbs:
应用/组件/按钮图标/ template.hbs:
<button>{{yield}}</button>
I also have a button-tooltip
component that should be displayed when the button is hovered over: 我还有一个
button-tooltip
组件,当按钮悬停时应显示该组件:
app/components/button-tooltip/component.js:
应用/组件/按钮工具提示/ component.js:
export default Ember.Component.extend({
// some code here to handle positioning
});
app/components/button-tooltip/template.hbs:
应用/组件/按钮工具提示/ template.hbs:
<div>{{yield}}</div>
In my template, I'd like to use both like so: 在我的模板中,我想像这样使用两者:
app/index/template.hbs:
应用程序/索引/ 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}}
How do I get the button-icon
to communicate with the button-tooltip
so that the tooltip is shown when the icon is hovered over? 如何让
button-icon
与button-tooltip
进行通信,以便在图标悬停时显示工具提示? If I only had one button, I can bind both the button and tooltip to a property on the controller, but I have a variable list of them to display. 如果我只有一个按钮,我可以将按钮和工具提示绑定到控制器上的属性,但我有一个变量列表要显示。 I can also wrap both components in another component (called
button-with-tooltip
or something), but this seems like it's starting to get into component-ception. 我也可以将这两个组件包装在另一个组件中(称为
button-with-tooltip
或者其他东西),但这似乎已经开始进入组件构建。
It's pretty complicated to set such kind of interactions when you have that templates. 当你拥有这些模板时,设置这种交互非常复杂。 Your components are fully independent, but they should have a parent-child connection, since they are actually the parent and a child.
您的组件完全独立,但它们应该具有父子连接,因为它们实际上是父组件和子组件。
A more suitable approach for me is below. 对我来说更合适的方法如下。
app/index/template.hbs
应用程序/索引/ template.hbs
{{#buttons-list buttons=property_with_a_correct_list_from_the_index_controller}}
app/components/button-list/template.hbs
应用程序/组件/按钮列表/ template.hbs
{{#each button in buttons}}
{{#button-icon data=button}}
{{/each}}
app/components/button-icon/template.hbs
应用/组件/按钮图标/ template.hbs
<div>{{data.title}}</div>
{{#button-tooltip data=data.tooltip}}
app/components/button-icon/component.js:
应用/组件/按钮图标/ component.js:
export default Ember.Component.extend({
tagName: 'button',
...
});
app/components/button-tooltip/template.hbs:
应用/组件/按钮工具提示/ template.hbs:
{{#if isPicture}}
<img src={{data.image}} />
{{else}}
{{data.text}}
{{/if}}
app/components/button-tooltip/component.js:
应用/组件/按钮工具提示/ component.js:
export default Ember.Component.extend({
tagName: 'div'
isPicture: function() {
this.get('data.type') == 'image'
}.property('data.type')
});
And the property_with_a_correct_list_from_the_index_controller
should look like this 而
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!'}}
]
Let's review it: 我们来看看吧:
tagName
property tagName
属性中的控制器 For now let's determine your high-level requirement for the sample: 现在让我们确定您对样本的高级要求:
As you can see the icon component totally controls the tooltip visibility. 如您所见,图标组件完全控制工具提示可见性。 In this case I'd consider an approach with conditional template.
在这种情况下,我会考虑使用条件模板的方法。 For example:
例如:
app/components/button-icon/component.js:
应用/组件/按钮图标/ 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
});
app/components/button-icon/template.hbs
应用/组件/按钮图标/ template.hbs
<div>{{data.title}}</div>
{{#if showTooltip}}
{{#button-tooltip data=data.tooltip}}
{{/if}}
As you can see, your sample is rewritten in a more clear way, where you can see a approach to control tooltip visibility. 如您所见,您的样本以更清晰的方式重写,您可以在其中看到控制工具提示可见性的方法。 I'd recommend to use such approach only in case when you need to control the tooltip visibility.
我建议仅在需要控制工具提示可见性时才使用此方法。
Back to 回到
more code here to handle other stuff
这里有更多代码来处理其他内容
For this I would recommend to not discard your approach with binding of a property. 为此,我建议不要放弃绑定属性的方法。 Just create a property with a required state in the
button-icon
component and make a corresponding computed property in the button-tooltip
component, which will be listening for changes in the property. 只需在
button-icon
组件中创建一个具有所需状态的属性,并在button-tooltip
组件中创建相应的计算属性,该组件将侦听属性中的更改。
Example: 例:
app/components/button-icon/component.js:
应用/组件/按钮图标/ 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
});
app/components/button-icon/template.hbs
应用/组件/按钮图标/ template.hbs
<div>{{data.title}}</div>
{{#button-tooltip data=data.tooltip props=tooltipProps}
app/components/button-tooltip/component.js:
应用/组件/按钮工具提示/ 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 But the first approach I like more %) PS但我喜欢的第一种方法更多%)
Once you are using a version of ember that supports yielding values in a component, I think this is 1.10.0, you can do the following, which is very intuitive. 一旦你使用支持在组件中产生值的ember版本,我认为这是1.10.0,你可以做到以下,这是非常直观的。
{{#button-icon as |active|}}
<div>Cat</div>
{{#button-tooltip active=active}}
<img src="cat.png">
{{/button-tooltip}}
{{/button-icon}}
And in your button-icon
component instead of sending an action up, you would set a value eg isActive
, and send that down. 在您的
button-icon
组件中,您可以设置一个值,例如isActive
,然后将其发送下来。
<button>{{yield isActive}}</button>
The idea is actions up, data down. 这个想法是行动起来,数据下降。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.