在ember中传播悬停事件

时间:2013-12-13 22:09:54

标签: javascript ember.js

我有一个列表,我想检测用户何时悬停在其中的li。问题是mouseEnter似乎没有传播。目前我正在使用这个:

// components/hover-pad.js
export default Ember.Component.extend({
    template: Em.Handlebars.compile('{{yield}}'),

    mouseEnter: function(){
        this.sendAction("action", this.get("ctx"));
    },

    action: function(){
        return "hover";
    }.property()
});

// components/project-picker.js
export default Ember.Component.extend({
    actions: {
        hover: function(ctx){
            console.log("caught propagated hover");
        }
    }
})

// templates/components/project-picker/hbs
<ul>
    {{#each project in projects}}
    <li>{{#hover-pad ctx="project"}}</li>
    {{/each}}
</ul>

这有效但我真的觉得我错过了一些恩赐启示,那会更加惯用于什么呢?

更新

我还应该提一下,除了悬停事件之外我还想捕获点击次数,这意味着无法使用动作助手。

4 个答案:

答案 0 :(得分:4)

{{#view App.ClickHoverView contextBinding=item}}
   {{item}}
{{/view}}

App.ClickHoverView = Em.View.extend({
  tagName:'li',
  click:function(){
     this.get('controller').send('click', this.get('context'));
  },
  mouseEnter:function(){
     this.get('controller').send('hover', this.get('context'));
  }
});

http://emberjs.jsbin.com/uQopETU/2/edit

答案 1 :(得分:1)

好的,这是一个更通用的解决方案,用于在父视图中触发操作并传入上下文。

// components/evented-tag.js
export default Ember.Component.extend(
    function(){
        var definition = {
            template: Ember.Handlebars.compile('{{yield}}'),
        };

        var events = Ember.A(["touchStart", "touchMove", "touchEnd", "touchCancel", "keyDown", "keyUp", "keyPress", "mouseDown", "mouseUp", "contextMenu", "click", "doubleClick", "mouseMove", "focusIn", "focusOut", "mouseEnter", "mouseLeave", "submit", "change", "dragStart", "drag", "dragEnter", "dragLeave", "dragOver", "drop", "dragEnd"]);

        var self = this;
        events.forEach(function(event){
            definition[event] = function(){
                var handlerName = "_" + event;
                if(this.get(handlerName)){
                    this.sendAction(handlerName, this.get("param"));    
                }
            }
        });

        return definition;
    }()
);

// templates/components/evented-tag.hbs
{{yield}}

并使用:

// templates/components/project_picker.hbs
<ul>
    {{#each project in projects}}
        {{#evented-tag tagName="li" param=project _mouseEnter="projectHovered", _click="projectClicked"}}
            {{project.name}}
        {{/evented-tag}}
    {{/each}}
</ul>

// components/project_picker.js
export default Ember.Component.extend({
 actions: {
    projectClicked: function(project){
        console.log("projectClicked");
        console.log(project);
    },

    projectHovered: function(project){
        console.log("projectHovered");
        console.log(project);
    }       
 }
});

答案 2 :(得分:0)

啊,你可以用App注册自定义事件。我所要做的就是添加:

var App = Ember.Application.extend({
  customEvents: {
    "mouseover": "mouseOver"
  }
});

并且因为mouseover向上传播视图,我可以在父视图中处理它:

// components/project-picker.js
export default Ember.Component.extend({
    mouseOver: function(ctx){
        console.log("caught propagated hover");
    }
})

答案 3 :(得分:0)

好的,现在尝试另一种方法,这次我创建一个自定义组件,用于列表中的每个项目。

export default Ember.Component.extend({
    tagName: "a",
    template: Ember.Handlebars.compile('{{project.name}}'),

    click: function(){
        this.sendAction('projectClicked', this.get("project"));
    },

    mouseOver: function(){
        this.sendAction('projectHovered', this.get("project"));
    },

    projectClicked: function(){
        return "projectClicked";
    }.property(),

    projectHovered: function(){
        return "projectHovered";
    }.property()
});

然后在主要组件中我为已发送的操作注册处理程序:

// components/project-picker.js
export default Ember.Component.extend({
    actions: {
        projectClicked: function(project){
            console.log("caught propagated hover");
        },
        projectHovered: function(project){
            console.log("caught propagated hover");
        } 
    }
})

这样可行,但它仍然感觉这里有一点点瑕疵,特别是sendAction方法的间接(调用到另一个属性)似乎很长时间。为什么不直接将动作的名称传递给sendAction?看起来我最终还是会为调度事件创建大量的组件。也许可以创建一个截取所有事件的通用链接,并将它们与上下文一起发送......