Определение области 'this' в TypeScript
У меня очень простой класс, но я уже столкнулся с болью с определением 'this в Typescript:
Typescript
/// <reference path='jquery.d.ts' />
/// <reference path='bootstrap.d.ts' />
module Problem {
export class Index {
detailsUrl: string;
constructor() {
$('.problem-detail-button').click((e) => {
e.preventDefault();
var $row = $(this).closest('tr'); //this must be that of the callback
var problemId: number = $row.data('problem-id');
$.ajax({
url: this.detailsUrl, //this must be the instance of the class
data: { id: problemId },
type: 'POST',
success: (result) => {
$('#details-modal-placeholder').html(result);
$('#details-modal-placeholder modal').modal('show');
},
})
});
}
}
}
Javascript
var Problem;
(function (Problem) {
var Index = (function () {
function Index() {
var _this = this;
$('.problem-detail-button').click(function (e) {
e.preventDefault();
var $row = $(_this).closest('tr');
var problemId = $row.data('problem-id');
$.ajax({
url: _this.detailsUrl,
data: {
id: problemId
},
type: 'POST',
success: function (result) {
$('#details-modal-placeholder').html(result);
$('#details-modal-placeholder modal').modal('show');
}
});
});
}
return Index;
})();
Problem.Index = Index;
})(Problem || (Problem = {}));
Теперь проблема в том, что строка
var $row = $(this).closest('tr'); //this must be that of the callback
и эта строка
this.detailsUrl, //this must be the instance of the class
конфликт в значении 'this'
Как вы обрабатываете смесь 'this'?
Ответы
Ответ 1
module Problem {
export class Index {
detailsUrl: string;
constructor() {
var that = this;
$('.problem-detail-button').click(function (e) {
e.preventDefault();
var $row = $(this).closest('tr'); //this must be that of the callback
var problemId: number = $row.data('problem-id');
$.ajax({
url: that.detailsUrl, //this must be the instance of the class
data: { id: problemId },
type: 'POST',
success: (result) => {
$('#details-modal-placeholder').html(result);
$('#details-modal-placeholder modal').modal('show');
},
})
});
}
}
}
Явно объявляю that = this
, поэтому у вас есть ссылка для that.detailsUrl
, затем
не используйте жирную стрелку для обработчика кликов, поэтому вы получите правильную область this
для обратного вызова.
Игровая площадка.
Ответ 2
Вам нужно вернуться к стандартному способу javascript. сохраните переменную как:
var self = this;
Затем вы можете использовать function
вместо ()=>
и использовать this
для доступа к переменной в обратном вызове и self
для доступа к экземпляру класса.
Вот полный пример кода:
module Problem {
export class Index {
detailsUrl: string;
constructor() {
var self = this;
$('.problem-detail-button').click(function(e){
e.preventDefault();
var $row = $(this).closest('tr'); //this must be that of the callback
var problemId: number = $row.data('problem-id');
$.ajax({
url: self.detailsUrl, //this must be the instance of the class
data: { id: problemId },
type: 'POST',
success: (result) => {
$('#details-modal-placeholder').html(result);
$('#details-modal-placeholder modal').modal('show');
},
})
});
}
}
}
// Creating
var foo:any = {};
foo.x = 3;
foo.y='123';
var jsonString = JSON.stringify(foo);
alert(jsonString);
// Reading
interface Bar{
x:number;
y?:string;
}
var baz:Bar = JSON.parse(jsonString);
alert(baz.y);
И ваш сгенерированный javascript:
var Problem;
(function (Problem) {
var Index = (function () {
function Index() {
var self = this;
$('.problem-detail-button').click(function (e) {
e.preventDefault();
var $row = $(this).closest('tr');
var problemId = $row.data('problem-id');
$.ajax({
url: self.detailsUrl,
data: {
id: problemId
},
type: 'POST',
success: function (result) {
$('#details-modal-placeholder').html(result);
$('#details-modal-placeholder modal').modal('show');
}
});
});
}
return Index;
})();
Problem.Index = Index;
})(Problem || (Problem = {}));
var foo = {
};
foo.x = 3;
foo.y = '123';
var jsonString = JSON.stringify(foo);
alert(jsonString);
var baz = JSON.parse(jsonString);
alert(baz.y);
Ответ 3
Если вы поддерживаете только браузеры с .addEventListener
, я бы предложил использовать это, чтобы связать ваши данные с вашими элементами.
Вместо того, чтобы внедрять ваш код, я просто приведу простой пример.
function MyClass(el) {
this.el = el;
this.foo = "bar";
el.addEventListener("click", this, false);
}
MyClass.prototype.handleEvent = function(event) {
this[event.type] && this[event.type](event);
};
MyClass.prototype.click = function(event) {
// Here you have access to the data object
console.log(this.foo); // "bar"
// ...and therefore the element that you stored
console.log(this.el.nodeName); // "DIV"
// ...or you could use `event.currentElement` to get the bound element
};
Таким образом, этот метод дает вам организованную связь между элементами и данными.
Даже если вам нужно поддерживать старый IE, вы можете закрепить его с помощью .attachEvent()
.
Итак, чтобы использовать его, вы просто передаете элемент конструктору при настройке данных.
new MyClass(document.body);
Если вся логика находится в вашем обработчике (-ах), вам даже не нужно указывать ссылку на созданный объект, поскольку обработчики автоматически получают ее через this
.
Ответ 4
Я обычно привязываю this
к переменной, как только у меня есть ее в области, которую я хочу.
Однако this
вы можете найти следующее:
constructor() {
var class_this=this;
$('.problem-detail-button').click(function (e) {
e.preventDefault();
var callback_this=e.target;
Ответ 5
Поздно к потоку, но у меня есть что-то другое, чем предложение.
Вместо:
var $row = $(this).closest('tr'); //this must be that of the callback
Рассмотрим использование:
var $row = $(e.currentTarget).closest('tr');
Как и в этом примере, где угодно, вы можете использовать this
в обратном вызове jQuery, у вас есть доступ к параметру функции, который вы можете использовать вместо этого. Я бы предположил, что использование этих параметров вместо this
является более чистым (где "чище" определяется как более выразительное и менее вероятно, что оно будет превращено в ошибку во время будущего обслуживания).
Ответ 6
module Problem {
export class Index {
constructor() {
$('.classname').on('click',$.proxy(this.yourfunction,this));
}
private yourfunction(event){
console.log(this);//now this is not dom element but Index
}
}
}
проверьте jquery.proxy().
просто напомните, что есть другой способ.