在 CustomElement 中引用 self (this)
Reference to self (this) inside CustomElement
我正在使用此 polyfill 在 JavaScript 中实现自定义元素。然而,self
变量在我的方法中引用了 Window
,除非我先调用 const self = this
。
任何人都可以解释一下为什么对我来说如此,并且也许可以建议一种在方法中访问自定义元素实例的更好方法吗?
class DocumentPreview extends HTMLElement {
constructor(self, documents) {
self = super(self);
self.documents = documents || [];
self.innerHTML = Handlebars.templates['document_preview']();
}
connectedCallback() {
// if I don't do this first ...
const self = this; // <<----------------------------------
console.log("connected now");
document.addEventListener('mqttsub', function(event) {
// ... onMessage is undefined here:
self.onMessage(event.detail);
});
}
disconnectedCallback() {
console.log("disconnected");
}
onMessage(message) {
// Same story ...
const self = this; // <<----------------------------------
Promise.resolve(true)
.then(json("/documents/"))
.then(ds => ds
.filter(x => x.name==message.payload)
.reduce((x, y) => y, undefined)
)
.then(d => json(sprintf("/document/%d/", d.id))())
// ... here:
.then(d => self.renderDocuments(d))
.catch(console.log);
}
renderDocuments(d) {
console.log('render', d);
}
}
在JavaScript中的this
关键字,指的是当前函数的上下文。
document.addEventListener('mqttsub', function(event) {
// this here corresponds to your function(event) {...} context
this.onMessage(event.detail); // Will fail
});
解决这个问题的一个简单方法是使用箭头函数。箭头函数默认使用外部上下文。
document.addEventListener('mqttsub', (event) => {
// this here corresponds to the outer context = your class
this.onMessage(event.detail);
});
否则你也可以绑定上下文
document.addEventListener('mqttsub', (function(event) {
this.onMessage(event.detail);
}).bind(this)); // Set the function context to be the class context
尝试使用 bind()
在构造函数中绑定方法 onMessage()
和 renderDocuments()
,如 this.methodName = this.methodName.bind(this)
中那样。有了这个,您将能够通过 this
.
访问属性和方法
class DocumentPreview extends HTMLElement {
constructor(documents) {
super();
this.documents = documents || [];
this.innerHTML = Handlebars.templates['document_preview']();
this.onMessage = this.onMessage.bind(this);
this.renderDocuments = this.renderDocuments.bind(this);
}
connectedCallback() {
document.addEventListener('mqttsub', this.onMessage);
}
disconnectedCallback() {
console.log("disconnected");
}
onMessage(event) {
const { detail: message } = event;
Promise.resolve(true)
.then(json("/documents/"))
.then(ds => ds
.filter(x => x.name==message.payload)
.reduce((x, y) => y, undefined)
)
.then(d => json(sprintf("/document/%d/", d.id))())
// ... here:
.then(d => this.renderDocuments(d))
.catch(console.log);
}
renderDocuments(d) {
console.log('render', d);
}
}
希望对您有所帮助!
我正在使用此 polyfill 在 JavaScript 中实现自定义元素。然而,self
变量在我的方法中引用了 Window
,除非我先调用 const self = this
。
任何人都可以解释一下为什么对我来说如此,并且也许可以建议一种在方法中访问自定义元素实例的更好方法吗?
class DocumentPreview extends HTMLElement {
constructor(self, documents) {
self = super(self);
self.documents = documents || [];
self.innerHTML = Handlebars.templates['document_preview']();
}
connectedCallback() {
// if I don't do this first ...
const self = this; // <<----------------------------------
console.log("connected now");
document.addEventListener('mqttsub', function(event) {
// ... onMessage is undefined here:
self.onMessage(event.detail);
});
}
disconnectedCallback() {
console.log("disconnected");
}
onMessage(message) {
// Same story ...
const self = this; // <<----------------------------------
Promise.resolve(true)
.then(json("/documents/"))
.then(ds => ds
.filter(x => x.name==message.payload)
.reduce((x, y) => y, undefined)
)
.then(d => json(sprintf("/document/%d/", d.id))())
// ... here:
.then(d => self.renderDocuments(d))
.catch(console.log);
}
renderDocuments(d) {
console.log('render', d);
}
}
在JavaScript中的this
关键字,指的是当前函数的上下文。
document.addEventListener('mqttsub', function(event) {
// this here corresponds to your function(event) {...} context
this.onMessage(event.detail); // Will fail
});
解决这个问题的一个简单方法是使用箭头函数。箭头函数默认使用外部上下文。
document.addEventListener('mqttsub', (event) => {
// this here corresponds to the outer context = your class
this.onMessage(event.detail);
});
否则你也可以绑定上下文
document.addEventListener('mqttsub', (function(event) {
this.onMessage(event.detail);
}).bind(this)); // Set the function context to be the class context
尝试使用 bind()
在构造函数中绑定方法 onMessage()
和 renderDocuments()
,如 this.methodName = this.methodName.bind(this)
中那样。有了这个,您将能够通过 this
.
class DocumentPreview extends HTMLElement {
constructor(documents) {
super();
this.documents = documents || [];
this.innerHTML = Handlebars.templates['document_preview']();
this.onMessage = this.onMessage.bind(this);
this.renderDocuments = this.renderDocuments.bind(this);
}
connectedCallback() {
document.addEventListener('mqttsub', this.onMessage);
}
disconnectedCallback() {
console.log("disconnected");
}
onMessage(event) {
const { detail: message } = event;
Promise.resolve(true)
.then(json("/documents/"))
.then(ds => ds
.filter(x => x.name==message.payload)
.reduce((x, y) => y, undefined)
)
.then(d => json(sprintf("/document/%d/", d.id))())
// ... here:
.then(d => this.renderDocuments(d))
.catch(console.log);
}
renderDocuments(d) {
console.log('render', d);
}
}
希望对您有所帮助!