Wie führe ich die Basisklasse der Vererbungskette direkt in Javascript (OOP) aus?
P粉718165540
P粉718165540 2024-01-10 17:20:07
0
1
409

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方法最后他们无论如何应该使用渲染器renderMethodenklasse (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.renderIch 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

Renderer.render

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

Children

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我想用一些预定义的 elcontent 等在他们自己的 .render() 方法中覆盖它,但是如果我尝试执行 renderer.render() 方法来自 Renderer 内部,它遍历整个链,我的参数丢失了,因为在 MailboxInbox 中,渲染方法当前没有'不接受任何参数,所以我要么应该让它接受参数并将它们传递到整个链,要么只是在 Renderer 中定义一些专用类,如 baseRenderRenderer< /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 🎜

P粉718165540
P粉718165540

Antworte allen(1)
P粉618358260

从技术上讲,您可以将 this.render(el, text); 替换为

Renderer.prototype.render.call(this, el, text);

它绕过了继承的属性查找。然而,这通常不是一个好的做法,会丧失class继承的优势。

幸运的是,您已经确定了更新中的实际问题:

这确实错误地覆盖了具有不兼容签名的方法,违反了里氏替换原则

您也已经确定了潜在的解决方案:

两个都很好。在后者中,我建议不要命名方法 renderbaseRender,而是推荐类似 renderContent(el, content)renderDefault (el),它们的签名实际上不同 - 并且都可以被覆盖。然而,看看使用两个参数调用时 render 的实现,在我看来,除了调用 el.appendChild(content) 之外,它实际上没有做任何有用的事情,所以我'宁愿完全放弃它并只调用 appendChild (除非您需要覆盖具体行为的能力,例如通过执行 el.prepend(content) 来代替)。

Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage