2017-11-22 5 views
0

Ich verwende dieses polyfill ein eigenes Element in JavaScript zu implementieren. Die self Variable bezieht sich jedoch auf Window innerhalb meiner Methoden, wenn ich zuerst const self = this aufrufen.Verweis auf sich selbst (dieser) innerhalb CustomElement

Kann jemand freundlicherweise erklären, warum das ist für mich und vielleicht einen besseren Weg vorschlagen, die benutzerdefinierten Elementinstanz innerhalb von Methoden zugreifen?

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); 
    } 
} 
+0

Die 'self' Parameter im Konstruktor nicht auf andere Methoden zugänglich sein würden, das ist ein Grundumfang Thema. Wenn Sie Pfeilfunktionen wie in 'onMessage()' verwenden, brauchen Sie die 'self' Variable nicht, Sie können' this' direkt verwenden. Für eine Nicht-Pfeil-Funktion wie in Ihrem Event-Listener-Callback können Sie entweder tun, was Sie gezeigt haben oder '.bind (this)' mit diesem Callback verwenden und dann 'this' anstelle von' self' im Callback. – nnnnnn

Antwort

2

Bindung Probieren Sie die Methoden onMessage() und renderDocuments() im Konstruktor bind() wie in this.methodName = this.methodName.bind(this) verwenden. Damit können Sie über this auf Eigenschaften und Methoden zugreifen.

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); 
    } 
} 

Hoffentlich hilft das!

+0

Großartig, und darüber hinaus verbessert es deutlich die Lesbarkeit. Kurz: Wie nennt man diese Konstruktion in JS: 'const {detail: message} = event;' Gibt es einen bestimmten Namen für diese Art von Mustererkennung? –

+0

Die Frage von OP war auf einer grundlegenden Ebene umgebend, die 'this' keiner Variablen innerhalb jeder Methode zuweisen musste. Der 'bind()' Ansatz sollte dabei helfen, indem sichergestellt wird, dass Klassenmethoden den gewünschten Umfang haben. –

+0

@ 沖 原 ハ ー ベ ス ト Das nennt man [Destrukturierung Zuordnung] (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment) in ES6. In diesem Fall entpackt er die Variable mit dem Schlüssel 'detail' und weist ihr einen Alias ​​/ Namen von 'message' zu. Vielen Dank! –

1

in JavaScript das this Schlüsselwort, bezieht sich auf den Kontext des aktuellen Funktion.

Eine einfache Möglichkeit, dies zu beheben, ist die Verwendung einer Pfeilfunktion. Pfeilfunktionen verwenden standardmäßig den äußeren Kontext.

document.addEventListener('mqttsub', (event) => { 
    // this here corresponds to the outer context = your class 
    this.onMessage(event.detail); 
}); 

Ansonsten können Sie auch den Kontext binden

document.addEventListener('mqttsub', (function(event) { 
    this.onMessage(event.detail); 
}).bind(this)); // Set the function context to be the class context 
Verwandte Themen