Javascript 将html事件绑定到构造函数中控制器类的实例
抱歉,关于将处理程序绑定到实例,可能有一点noobjs问题 我正在创建一个控制器实例,其中包含一些数据,这些数据随后将用于处理传入事件(实际用例是使用不同的ajax URL组合复杂的d3处理程序,并在其中组合执行实际树更新的函数) RequireJS和jquery都涉及其中,但我怀疑我的问题更多地与我的特定绑定代码有关。我想我可以放弃使用“this”,因为我每页只有一个控制器,可以是全局控制器。但这感觉应该是可行的,只要我知道怎么做 这就是我如何从构造函数内部将控制器绑定到其目标上的方法(在构造函数外部执行此操作似乎有效): 出了什么问题? 当我单击按钮时,handleClick中的“this”指的是html按钮,而不是控制器实例 如果我直接调用控制器实例方法,“this”是正确的 我已尝试调用或创建包装器函数,如中所示 My button click一直将“this”视为按钮,而不是控制器: 输出Javascript 将html事件绑定到构造函数中控制器类的实例,javascript,jquery,Javascript,Jquery,抱歉,关于将处理程序绑定到实例,可能有一点noobjs问题 我正在创建一个控制器实例,其中包含一些数据,这些数据随后将用于处理传入事件(实际用例是使用不同的ajax URL组合复杂的d3处理程序,并在其中组合执行实际树更新的函数) RequireJS和jquery都涉及其中,但我怀疑我的问题更多地与我的特定绑定代码有关。我想我可以放弃使用“this”,因为我每页只有一个控制器,可以是全局控制器。但这感觉应该是可行的,只要我知道怎么做 这就是我如何从构造函数内部将控制器绑定到其目标上的方法(在构造
global var controller:BtnMgr.I am a button
this:[object HTMLButtonElement],type:
e:[object Object],type:Object
BtnMgr.handleClick:this.msg:undefined
简化版:
HTML
page4.html
<!DOCTYPE html>
<html>
<head>
<title>Page 4</title>
<script type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/require.js/2.1.15/require.min.js"></script>
<script type="text/javascript">
requirejs.config({
baseUrl: '.',
paths: {
"jquery": "//ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min"
}
});
var controller;
require(["main4"], function(BtnMgr) {
controller = new BtnMgr("I am a button", "btn_click");
//this simulated call works - 'this' refers to the BtnMgr instance
controller.handleClick("dummy_btn");
});
</script>
</head>
<body>
<button id="btn_click">click me!</button>
</body>
</html>
绑定onClick时请尝试以下操作:
function BtnMgr(msg, tgt_id) {
this.msg = msg;
this.tgt_id = tgt_id;
var selector = "#" + tgt_id;
$(selector).on("click", $.proxy(this.handleClick, this));
}
这将确保回调中的“this”变量是您的类,而不是clickevent。
您可以在此处阅读有关jQuery代理的更多信息:您可以(几乎)实现您想要的:
$(selector).on("click", this.handleClick.bind(this));
此
将是BtnMgr的实例,e.target
将一如既往地作为按钮
然而,这将与传统背道而驰,并使任何试图理解您的代码的人感到困惑,包括您自己。在单击处理程序中,这个
应该总是引用单击的元素,这是很自然的
如果您真的必须从处理程序获得一个指向附加单击的BtnMgr实例的引用,那么我可能会选择这样的“e-augmentation”:
function BtnMgr(msg, tgt_id) {
var that = this;
this.msg = msg;
this.tgt_id = tgt_id;
var selector = "#" + tgt_id;
$(selector).on("click", function(e) {
e.clickAttacher = that;
that.handleClick(e);
});
}
BtnMgr.prototype.toString = function(){
return "BtnMgr." + this.msg;
};
BtnMgr.prototype.handleClick = function(e) {
console.log("click attacher was instance of : " + e.clickAttacher.constructor.name); // BtnMgr
console.log("button id: " + e.target.id); // xxx
console.log("msg: " + e.clickAttacher.msg); // Hello World!
};
var b = new BtnMgr('Hello World!', 'xxx');
这样做之后,您必须问这样定义
handleClick
是否真的值得。当然,如果它是一个怪物函数,那么是的,用BtnMgr.prototype….
定义它,但是如果它很小,那么就在构造函数中定义它,并直接利用在作用域链中的作用(就像上面的增强函数一样)。让我检查一下,但是是的,我认为代理是我想要的。我在别处遇到了另一个相同类型的错误——糟糕的“this”。关于“说Javascript”,作者说,当调用存储在变量中的方法时,需要重复实例变量。我怀疑$的代理会这样做,还有更多。在Python上,一旦您存储了对实例方法的引用,它就会从那时起知道该实例,因此我从JS中假设了同样的情况。请注意,这也花了我很长时间才弄清楚。是的,代理方法创建了一个带有“this”的变量,然后使用存储的对“this”的引用对该方法调用apply。如果你想更多地了解它的工作原理,你可以在谷歌上搜索“js应用”。丹和你都有正确的想法,那就是使用$.proxy或bind来强制“this”中的内容。bind似乎更适合现代JS,所以我选择它。我不想让“this”引用按钮的原因是,在我的实际使用中,这只是一个manager对象的事件。经理通过requirejs加载了许多松散耦合的模块:一个带有样板文件的通用d3树模块。不同的页面有不同的d3模块来添加要调用的节点和ajax URL。管理器“this”协调所有处理,因此事件的起源无关紧要。
function BtnMgr(msg, tgt_id) {
this.msg = msg;
this.tgt_id = tgt_id;
var selector = "#" + tgt_id;
$(selector).on("click", $.proxy(this.handleClick, this));
}
$(selector).on("click", this.handleClick.bind(this));
function BtnMgr(msg, tgt_id) {
var that = this;
this.msg = msg;
this.tgt_id = tgt_id;
var selector = "#" + tgt_id;
$(selector).on("click", function(e) {
e.clickAttacher = that;
that.handleClick(e);
});
}
BtnMgr.prototype.toString = function(){
return "BtnMgr." + this.msg;
};
BtnMgr.prototype.handleClick = function(e) {
console.log("click attacher was instance of : " + e.clickAttacher.constructor.name); // BtnMgr
console.log("button id: " + e.target.id); // xxx
console.log("msg: " + e.clickAttacher.msg); // Hello World!
};
var b = new BtnMgr('Hello World!', 'xxx');