打字稿:如何从公共函数访问和更新类变量



我正在尝试访问函数setRating()中类变量的值,但控制台打印是"未定义的"。

export class UserFeedbackComponent implements OnInit {    
rating: number;    
constructor() {
this.rating = 3;
}    
ngOnInit() {
//initial setup
console.log("Rating " + this.rating);
document.addEventListener('DOMContentLoaded', function() {
let stars = document.querySelectorAll('.star');
stars.forEach(function(star) {
star.addEventListener('click', setRating);
});
let temps = parseInt(document.querySelector('.stars').getAttribute('data-rating'));
console.log("Rating 2: " + this.rating);
let target = stars[temps - 1];
target.dispatchEvent(new MouseEvent('click'));   
});    
}

function setRating(ev) {
//Printing 'undefined' in console.log
console.log('At top: ' + this.rating);
let span = ev.currentTarget;
let stars = document.querySelectorAll('.star');
let match = false;
let num = 0;
stars.forEach(function(star, index) {
if (match) {
star.classList.remove('rated');
} else {
star.classList.add('rated');
}
//are we currently looking at the span that was clicked
if (star === span) {
match = true;
num = index + 1;
}
});
this.rating = num;
console.log("value after update: " + this.rating)
document.querySelector('.stars').setAttribute('data-rating', num.toString());    
}
}
">

更新后的值:"控制台日志打印"未定义",除非将此.rating分配给 num。有人可以帮我如何在 setRating() 函数中访问评级变量的值以及如何更新其值吗?

这是一个上下文绑定问题,您必须将setRating函数绑定到类this否则它将使用自己的this,这与无法访问this.ratingthis类不同。您可以通过使用setRating.bind(this)来实现此目的。

首先,可以将DOMContentLoaded更改为箭头函数,以便继承上下文的this,如下所示:

document.addEventListener('DOMContentLoaded', () => {
// this.rating is visible here now
...
})

然后,您可以对forEach处理程序执行相同的操作:

stars.forEach((star) => {
// this.rating is visible here now too
...
});

最后,您可以将外部函数的this绑定到类this

star.addEventListener('click', setRating.bind(this));

你的最终代码将类似于下面:

export class UserFeedbackComponent implements OnInit {
rating: number;
constructor() {
this.rating = 3;
}
ngOnInit() {
//initial setup
console.log("Rating " + this.rating);
document.addEventListener('DOMContentLoaded', () => {
let stars = document.querySelectorAll('.star');
stars.forEach((star) => {
star.addEventListener('click', setRating.bind(this));
});
let temps = parseInt(document.querySelector('.stars').getAttribute('data-rating'));
console.log("Rating 2: " + this.rating);
let target = stars[temps - 1];
target.dispatchEvent(new MouseEvent('click'));
});
}
function setRating(ev) {
//Printing 'undefined' in console.log
console.log('At top: ' + this.rating);
let span = ev.currentTarget;
let stars = document.querySelectorAll('.star');
let match = false;
let num = 0;
stars.forEach(function(star, index) {
if (match) {
star.classList.remove('rated');
} else {
star.classList.add('rated');
}
//are we currently looking at the span that was clicked
if (star === span) {
match = true;
num = index + 1;
}
});
this.rating = num;
console.log("value after update: " + this.rating)
document.querySelector('.stars').setAttribute('data-rating', num.toString());
}
}

进一步观察:您正在类中声明一个function,这是完全不必要的,您可以将其声明为成员

export class UserFeedbackComponent implements OnInit { 
...
setRating(ev) {
...
}
}

然后你甚至不需要绑定它来这样称呼它:

star.addEventListener('click', ev => this.setRating(ev));

您不必在类中使用function关键字定义函数。 将其声明为类成员,您应该能够正常访问它。这是 Typescript 类声明中的最佳实践。

前任:

export class UserFeedbackComponent implements OnInit {    
rating: number;    
constructor() {
this.rating = 3;
}    
ngOnInit() {
//initial setup
console.log("Rating " + this.rating);
......................more code............
}

setRating(ev) {
//Printing 'undefined' in console.log
console.log(this.rating); //should work fine
// do other stuff with class members
}
}

最新更新