Ich arbeite an einer Vererbungskette aus 3 erweiterbaren Klassen.
Renderer (Basis) -> Mailbox (untergeordnetes Element) -> MailboxInbox (letztes untergeordnetes Element)
Sie haben jeweils ihre eigene render
方法。孩子只是重写渲染器(基础)render
方法最后他们无论如何应该使用渲染器的render
Methodenklasse (Basis< /strong>). Mein Problem ist, dass, wenn ich bestimmte Methoden in der Renderer-Klasse (createElementWithTextInside) ausführe, nicht genau die Renderer-Rendermethode (Renderer .render()) ausgeführt wird, sondern dies von der erweiterbaren Klasse aus am Ende der Kette. Es beginnt zum Beispiel mit der Traversierung:
1 -
MailboxInbox.render
2 -
Mailbox.render
3 -
Renderer.render
Ich verstehe, wie JS-Klassen/Vererbung hinter den Kulissen funktionieren. Javascript erweitert lediglich die Objektprototypen und das Skript iteriert darüber usw. Aber meine Frage ist: Wie kann ich dieses Verhalten vermeiden und bei Bedarf die Methode
in ihrer Methode direkt aufrufen? Ich kann
__self nicht im Renderer speichern, da es sowieso auf das der aktuellen Instanz (MailboxInbox) verweisen würde. Außerdem kann ich .bind/lambda (Pfeilfunktion) this
nicht verwenden, da ich den Kontext speichern muss
Violine
class Renderer { get noResultContent() { const p = this.createElement('p', 'no-result-msg'); const textNode = document.createTextNode('No result'); p.appendChild(textNode); return p; }; createElement(tag, className) { if (!tag) throw new Error('Tag must be passed!'); const res = document.createElement(tag); res.classList.add(className); return res; } createTextNode(text) { const res = document.createTextNode(text); return res; } /** * automatically creates an el based on tag, text node and insert the text node into the el */ createElementWithTextInside(tag, className, content) { const el = this.createElement(tag, className); const text = this.createTextNode(content); this.render(el, text); return el; } checkIfDomEl = el => el instanceof Element; render(el, content) { console.log('3: RENDERER RENDER') if (!this.checkIfDomEl(el)) throw new Error(`Please, pass the valid DOM el. Received: ${el}, ${typeof el} `); const finalContent = content || this.noResultContent; el.appendChild(finalContent); } } -------- class Mailbox extends Renderer { rootEl; constructor(selector) { super(); this.rootEl = document.querySelector(selector); } renderTitle(content) { if (!content) return null; const titleEl = super.createElementWithTextInside('h3', 'mailbox-title', content) super.render(this.rootEl, titleEl); } render() { console.log('2: MAILBOX RENDER') super.render(this.rootEl); } } -------- class MailboxInbox extends Mailbox { title = "Inbox" constructor(params) { const { selector } = params; super(selector); } renderTitle() { super.renderTitle(this.title); } render() { console.log('1: INBOX RENDER') super.render(); } } -------- const inbox = new MailboxInbox({selector: '#container'}); inbox.renderTitle()
Hier wird es nur in der Konsole gerendert:
1: Posteingangsrendering
2: Mailbox-Rendering
3: Renderer-Rendering
Danke für deine Hilfe! Mit freundlichen Grüße!
Aktualisiert
Im Grunde möchte ich nur eine grundlegende render
-Klasse haben, die folgende Parameter akzeptieren kann: (el,content)
(Inhalt ist optional) und
Ich möchte einige vordefinierte < verwenden code>el und content
usw. überschreiben es in ihren eigenen .render()
-Methoden, aber wenn ich versuche, renderer.render() auszuführen Die
-Methode kommt von innen render
类,它可以接受参数:(el,content)
(内容是可选的)和Children我想用一些预定义的 el
和 content
等在他们自己的 .render()
方法中覆盖它,但是如果我尝试执行 renderer.render()
方法来自 Renderer 内部,它遍历整个链,我的参数丢失了,因为在 MailboxInbox 中,渲染方法当前没有'不接受任何参数,所以我要么应该让它接受参数并将它们传递到整个链,要么只是在 Renderer 中定义一些专用类,如 baseRender
Renderer< /p> und durchläuft die gesamte Kette und meine Parameter fehlen, weil in 🎜MailboxInbox🎜 die Rendermethode derzeit keine Parameter akzeptiert, also sollte ich sie entweder dazu bringen, Parameter zu akzeptieren und sie zu übergeben in der gesamten Kette oder definieren Sie einfach eine dedizierte Klasse wie baseRender
in 🎜Renderer🎜 und rufen Sie sie direkt auf 🎜
从技术上讲,您可以将
this.render(el, text);
替换为它绕过了继承的属性查找。然而,这通常不是一个好的做法,会丧失
class
继承的优势。幸运的是,您已经确定了更新中的实际问题:
这确实错误地覆盖了具有不兼容签名的方法,违反了里氏替换原则。
您也已经确定了潜在的解决方案:
两个都很好。在后者中,我建议不要命名方法
render
和baseRender
,而是推荐类似renderContent(el, content)
和renderDefault (el)
,它们的签名实际上不同 - 并且都可以被覆盖。然而,看看使用两个参数调用时render
的实现,在我看来,除了调用el.appendChild(content)
之外,它实际上没有做任何有用的事情,所以我'宁愿完全放弃它并只调用appendChild
(除非您需要覆盖具体行为的能力,例如通过执行el.prepend(content)
来代替)。