Comment exécuter directement la classe de base de la chaîne d'héritage en Javascript (POO) ?
P粉718165540
P粉718165540 2024-01-10 17:20:07
0
1
382

Je travaille sur une chaîne d'héritage de 3 classes extensibles.

Renderer (base) -> Mailbox (enfant) -> MailboxInbox (dernier enfant)

Ils ont chacun leur propre classe render方法。孩子只是重写渲染器(基础)render方法最后他们无论如何应该使用渲染器rendermethod(Base< /strong>). Mon problème est que lorsque j'exécute certaines méthodes dans la classe Renderer (createElementWithTextInside), elle n'exécute pas exactement la méthode Renderer (Renderer .render()), mais elle le fait à partir de la classe extensible. au bout de la chaîne. Par exemple, il commence à parcourir :

1 - MailboxInbox.render

2 - Mailbox.render

3 - Renderer.render

Je comprends comment fonctionnent les classes/héritage js dans les coulisses. Javascript étend simplement les prototypes d'objets et le script les parcourra, etc. Mais ma question est la suivante : comment puis-je éviter ce comportement et appeler directement la méthode Renderer.render dans sa méthode en cas de besoin ?

Je ne peux pas enregistrer __self dans le renderer car cela pointerait de toute façon vers le this de l'instance actuelle (MailboxInbox). De plus, je ne peux pas utiliser .bind/lambda (fonction flèche) car je dois enregistrer le contexte

Violon

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()

Ici, le rendu s'effectue simplement dans la console :

1 : Rendu de la boîte de réception

2 : Rendu de la boîte aux lettres

3 : Rendu du moteur de rendu

Merci pour votre aide ! cordialement!

Mise à jour

Fondamentalement, je veux juste avoir une classe render de base qui peut accepter des paramètres : (el,content) (le contenu est facultatif) et render 类,它可以接受参数:(el,content)(内容是可选的)和Children我想用一些预定义的 elcontent 等在他们自己的 .render() 方法中覆盖它,但是如果我尝试执行 renderer.render() 方法来自 Renderer 内部,它遍历整个链,我的参数丢失了,因为在 MailboxInbox 中,渲染方法当前没有'不接受任何参数,所以我要么应该让它接受参数并将它们传递到整个链,要么只是在 Renderer 中定义一些专用类,如 baseRenderChildren< /p>Je souhaite utiliser Certains < prédéfinis code>el et content etc. le remplacent dans leurs propres méthodes .render(), mais si j'essaie d'exécuter Le renderer.render( ) vient de l'intérieur de 🎜Renderer🎜 et passe par toute la chaîne et mes paramètres sont manquants car dans 🎜MailboxInbox🎜 la méthode de rendu n'accepte actuellement aucun paramètre, donc je devrais soit la faire Accepter les paramètres et passer les tout au long de la chaîne, ou définissez simplement une classe dédiée comme baseRender dans 🎜Renderer🎜 et appelez-la directement 🎜

P粉718165540
P粉718165540

répondre à tous(1)
P粉618358260

Techniquement, vous pouvez remplacer this.render(el, text); par

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

Il contourne la recherche de propriétés héritées. Cependant, ce n’est généralement pas une bonne pratique et cela fera perdre les avantages de l’héritage. class

Heureusement, vous avez identifié le véritable problème avec votre mise à jour :

Cela remplace incorrectement une méthode avec une signature incompatible, violant ainsi le

Principe de substitution de Richter.

Vous avez également identifié des solutions potentielles :

Les deux sont bons. Dans ce dernier, je recommande plutôt de ne pas nommer la méthode

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

Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal