Tod*_*odd 73 jquery typescript
我试图在TypeScript中编写一个类,该类具有一个定义的方法,该方法充当jQuery事件的事件处理程序回调.
class Editor {
textarea: JQuery;
constructor(public id: string) {
this.textarea = $(id);
this.textarea.focusin(onFocusIn);
}
onFocusIn(e: JQueryEventObject) {
var height = this.textarea.css('height'); // <-- This is not good.
}
}
Run Code Online (Sandbox Code Playgroud)
在onFocusIn事件处理程序中,TypeScript将"this"视为该类的"this".但是,jQuery会覆盖此引用并将其设置为与事件关联的DOM对象.
另一种方法是在构造函数中将lambda定义为事件处理程序,在这种情况下,TypeScript会创建一种带有隐藏_this别名的闭包.
class Editor {
textarea: JQuery;
constructor(public id: string) {
this.textarea = $(id);
this.textarea.focusin((e) => {
var height = this.textarea.css('height'); // <-- This is good.
});
}
}
Run Code Online (Sandbox Code Playgroud)
我的问题是,是否有另一种方法来使用TypeScript在基于方法的事件处理程序中访问此引用,以克服此jQuery行为?
Fen*_*ton 98
this使用箭头函数语法时保留范围() => { ... }- 这是一个取自TypeScript For JavaScript Programmers的示例.
var ScopeExample = {
text: "Text from outer function",
run: function() {
setTimeout( () => {
alert(this.text);
}, 1000);
}
};
Run Code Online (Sandbox Code Playgroud)
需要注意的是this.text给你Text from outer function,因为箭头函数语法保留了"词法范围".
Ste*_*man 21
因此,如上所述,没有TypeScript机制来确保方法总是绑定到它的this指针(这不仅仅是一个jQuery问题.)这并不意味着没有一种合理直接的方法来解决这个问题.你需要的是为你的方法生成一个代理,this在调用你的回调之前恢复指针.然后,您需要使用该代理包装回调,然后再将其传递给事件.jQuery有一个内置的机制用于此调用jQuery.proxy().以下是使用该方法的上述代码示例(请注意添加的$.proxy()调用.)
class Editor {
textarea: JQuery;
constructor(public id: string) {
this.textarea = $(id);
this.textarea.focusin($.proxy(onFocusIn, this));
}
onFocusIn(e: JQueryEventObject) {
var height = this.textarea.css('height'); // <-- This is not good.
}
}
Run Code Online (Sandbox Code Playgroud)
这是一个合理的解决方案,但我个人发现开发人员经常忘记包含代理调用,所以我想出了一个基于TypeScript的替代解决方案来解决这个问题.使用,HasCallbacks下面的类你需要做的就是派生你的类HasCallbacks,然后任何前缀的方法'cb_'将this永久绑定它们的指针.您根本无法使用不同的this指针调用该方法,在大多数情况下这是更可取的.这两种机制都可以使用它,无论您发现哪种更容易使用.
class HasCallbacks {
constructor() {
var _this = this, _constructor = (<any>this).constructor;
if (!_constructor.__cb__) {
_constructor.__cb__ = {};
for (var m in this) {
var fn = this[m];
if (typeof fn === 'function' && m.indexOf('cb_') == 0) {
_constructor.__cb__[m] = fn;
}
}
}
for (var m in _constructor.__cb__) {
(function (m, fn) {
_this[m] = function () {
return fn.apply(_this, Array.prototype.slice.call(arguments));
};
})(m, _constructor.__cb__[m]);
}
}
}
class Foo extends HasCallbacks {
private label = 'test';
constructor() {
super();
}
public cb_Bar() {
alert(this.label);
}
}
var x = new Foo();
x.cb_Bar.call({});
Run Code Online (Sandbox Code Playgroud)
Sam*_*Sam 20
正如其他一些答案所述,使用箭头语法定义函数会导致引用this始终引用封闭类.
所以回答你的问题,这里有两个简单的解决方法.
constructor(public id: string) {
this.textarea = $(id);
this.textarea.focusin(e => this.onFocusIn(e));
}
Run Code Online (Sandbox Code Playgroud)
onFocusIn = (e: JQueryEventObject) => {
var height = this.textarea.css('height');
}
Run Code Online (Sandbox Code Playgroud)
您可以将成员函数绑定到构造函数中的实例.
class Editor {
textarea: JQuery;
constructor(public id: string) {
this.textarea = $(id);
this.textarea.focusin(onFocusIn);
this.onFocusIn = this.onFocusIn.bind(this); // <-- Bind to 'this' forever
}
onFocusIn(e: JQueryEventObject) {
var height = this.textarea.css('height'); // <-- This is now fine
}
}
Run Code Online (Sandbox Code Playgroud)
或者,只需在添加处理程序时绑定它.
this.textarea.focusin(onFocusIn.bind(this));
Run Code Online (Sandbox Code Playgroud)