MooTools 在方法和内部函数中绑定/保留类范围

发布于 2024-12-21 21:45:34 字数 724 浏览 0 评论 0原文

我正在尝试使用 Mootools 动态向页面添加按钮。除了 addButton 函数中的 addEvent 之外,一切都工作正常。我收到一条错误消息“对象 javascript:void(0); 的属性‘sayHi’不是函数”。

我认为这是由于我的范围所致,并且我必须以某种方式将 addButton 函数绑定回全局“this”?有人可以解释我做错了什么吗?谢谢!

var myClass = new Class({
    initialize: function(){
        this.sayHi();
    },

    sayHi: function(){
        alert('Hello World!');
    },

    addButton: function(){
        this.hiButton = new Element('a', {
            id: 'sayhi',
            html: 'Hi!',
            href: 'javascript:void(0);',
            events: {
                click: function(){
                    this.sayHi();
                }
            }
        }).inject($('myDiv'));
    }
});    

I'm trying to use Mootools to add a button to a page dynamically. It all works fine, except the addEvent in the addButton function. I get an error saying that "Property 'sayHi' of object javascript:void(0); is not a function".

I assume this is due to my scope and that I somehow must bind the addButton function back to the global "this"? Can someone explain what I'm doing wrong? Thanks!

var myClass = new Class({
    initialize: function(){
        this.sayHi();
    },

    sayHi: function(){
        alert('Hello World!');
    },

    addButton: function(){
        this.hiButton = new Element('a', {
            id: 'sayhi',
            html: 'Hi!',
            href: 'javascript:void(0);',
            events: {
                click: function(){
                    this.sayHi();
                }
            }
        }).inject($('myDiv'));
    }
});    

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

梦纸 2024-12-28 21:45:34

问题是,在您的单击处理程序中,this 值不再是原始对象,而是被单击的按钮。

可能有一种 MooTools 特定的方法来解决这个问题,但是将这个对象创建包装在一个函数中将是解决这个问题的一个简单的、本机的方法:

function getMyClass(){
   var self = new Class({
       initialize: function(){
           this.sayHi();
       },

       sayHi: function(){
           alert('Hello World!');
       },

       addButton: function(){
           this.hiButton = new Element('a', {
               id: 'sayhi',
               html: 'Hi!',
               href: 'javascript:void(0);',
               events: {
                   click: function(){
                       self.sayHi();
                   }
               }
          }).inject($('myDiv'));
       }
   });

   return self;
}    

然后

var myClass = getMyClass();

编辑

虽然上面是一个相当标准的习惯用法JavaScript,我听说它不能很好地与 MooTools 配合使用。如果是这样的话,我会同意这个(正如另一个答案已经提到的那样):

var myClass = new Class({
    initialize: function(){
        this.sayHi();
    },

    sayHi: function(){
        alert('Hello World!');
    },

    addButton: function(){
        var self;
        this.hiButton = new Element('a', {
            id: 'sayhi',
            html: 'Hi!',
            href: 'javascript:void(0);',
            events: {
                click: function(){
                    self.sayHi();
                }
            }
        }).inject($('myDiv'));
    }
});    

The problem is that in your click handler, the this value is no longer the original object, but rather the button that was clicked on.

There might be a MooTools-specific way to address this, but wrapping this object creation in a function would be a simple, native way to solve this:

function getMyClass(){
   var self = new Class({
       initialize: function(){
           this.sayHi();
       },

       sayHi: function(){
           alert('Hello World!');
       },

       addButton: function(){
           this.hiButton = new Element('a', {
               id: 'sayhi',
               html: 'Hi!',
               href: 'javascript:void(0);',
               events: {
                   click: function(){
                       self.sayHi();
                   }
               }
          }).inject($('myDiv'));
       }
   });

   return self;
}    

And then

var myClass = getMyClass();

EDIT

While the above is a fairly standard idiom in JavaScript, I'm told it doesn't play well with MooTools. If that's the case, I would go with this (as another answer already mentions):

var myClass = new Class({
    initialize: function(){
        this.sayHi();
    },

    sayHi: function(){
        alert('Hello World!');
    },

    addButton: function(){
        var self;
        this.hiButton = new Element('a', {
            id: 'sayhi',
            html: 'Hi!',
            href: 'javascript:void(0);',
            events: {
                click: function(){
                    self.sayHi();
                }
            }
        }).inject($('myDiv'));
    }
});    
好久不见√ 2024-12-28 21:45:34

您遇到此问题是因为当执行 click 处理程序时,this 代表的是 anchor 元素对象,而不是您的 myClass.

addButton 更改为:

addButton: function(){
    var that = this;
    this.hiButton = new Element('a', {
        id: 'sayhi',
        html: 'Hi!',
        href: 'javascript:void(0);',
        events: {
            click: function(){
                that.sayHi();
            }
        }
    }).inject($('myDiv'));
}

此处 是正在运行的例子。切换到代码视图以查看源代码。

You are getting this problem because when the click handler is executed this is representing the anchor element object and not to your myClass.

Change the addButton to:

addButton: function(){
    var that = this;
    this.hiButton = new Element('a', {
        id: 'sayhi',
        html: 'Hi!',
        href: 'javascript:void(0);',
        events: {
            click: function(){
                that.sayHi();
            }
        }
    }).inject($('myDiv'));
}

HERE is the running example. Switch to Code view to view source.

甜柠檬 2024-12-28 21:45:34

处理这个问题的推荐方法(在许多 mootools 中有更多插件)如下:

var myClass = new Class({
    initialize: function(){
        this.sayHi();
    },

    sayHi: function(){
        alert('Hello World!');
    },

    addButton: function(){
        var self = this;
        this.hiButton = new Element('a', {
            id: 'sayhi',
            html: 'Hi!',
            href: 'javascript:void(0);',
            events: {
                click: function(){
                    self.sayHi();
                }
            }
        }).inject($('myDiv'));
    }
});

您可以看到它与 Adam Rackis 解决方案非常相似,但您不需要使用函数调用来包装您的类。

恕我直言,它使代码变得更加干净/可维护/mooish!

希望这有帮助。

The recommended way of handling this and is in many mootools more plugins is as follows:

var myClass = new Class({
    initialize: function(){
        this.sayHi();
    },

    sayHi: function(){
        alert('Hello World!');
    },

    addButton: function(){
        var self = this;
        this.hiButton = new Element('a', {
            id: 'sayhi',
            html: 'Hi!',
            href: 'javascript:void(0);',
            events: {
                click: function(){
                    self.sayHi();
                }
            }
        }).inject($('myDiv'));
    }
});

You can see it is very similiar to Adam Rackis solution but you do not need to wrap your class with a function call.

IMHO it keeps the code a bit cleaner/maintanable/mooish!

Hope this helps.

指尖上得阳光 2024-12-28 21:45:34

天哪,绑定怎么样?这样做 var self = this; 是错误的。你可以这样做:

var myClass = new Class({
initialize: function(){
    this.sayHi();
},

sayHi: function(){
    alert('Hello World!');
},

addButton: function(){
    this.hiButton = new Element('a', {
        id: 'sayhi',
        html: 'Hi!',
        href: '#',
        events: {
            click: function(){
                this.sayHi();

                // this will stop event propagation
                return false;
            }.bind(this)
        }
    }).inject($('myDiv'));
}
});  

你可以在这里查看

Omg, what about bind? Doing var self = this; is just wrong. You can do something like this:

var myClass = new Class({
initialize: function(){
    this.sayHi();
},

sayHi: function(){
    alert('Hello World!');
},

addButton: function(){
    this.hiButton = new Element('a', {
        id: 'sayhi',
        html: 'Hi!',
        href: '#',
        events: {
            click: function(){
                this.sayHi();

                // this will stop event propagation
                return false;
            }.bind(this)
        }
    }).inject($('myDiv'));
}
});  

You can check it here

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文