Soluções para Herdar Componentes com Extends e Modificar o Template em Vue

Ao utilizar o extends em Vue para herdar um componente, a necessidade de adaptar parcialmente o template pode surgir. Esta técnica permite reutilizar opções como data, methods e computed, mas alterar o template diretamente apresenta desafios específicos.

O mecanismo do extends cria um novo cmoponente que incorpora as opções do componente pai, mas a estratégia de mesclagem do Vue não combina a opção template. Portanto, substituir o template por completo resulta na perda da estrutura original, enquanto reescrevê-lo integralmente compromete a reutilização.

Para contornar isso, existem diversas abordagens. Uma delas consiste em interceptar slots existentes no componente herdado. Suponha que o componente base tenha um slot nomeado footer; é possível injetar novos elementos virtuais nessa posição usando a função de renderização.

import ComponenteBase from './componente-base.vue';

export default {
  name: 'ComponenteExtendido',
  extends: ComponenteBase,
  methods: {
    executarAcao(confirmar) {
      // lógica da ação
    }
  },
  render(createElement) {
    this.$slots.footer = [
      createElement('button', {
        attrs: {
          type: 'button',
          disabled: !this.podeEnviar,
        },
        on: {
          click: () => { this.executarAcao(false); },
        },
      }, 'Ação Principal'),
      createElement('button', {
        on: {
          click: () => { this.executarAcao(true); },
        },
      }, 'Ação Secundária'),
      createElement('button', {
        on: {
          click: () => { this.visivel = false; },
        },
      }, 'Fechar'),
    ];
    return ComponenteBase.render.call(this, createElement);
  },
};

Outra técnica envolve a mesclagem manual do template. Utilizando o gancho beforeCreate, é possível envolver o template original em um elemento adicional.

import ComponentePai from './componente-pai.vue';

export default {
  extends: ComponentePai,
  beforeCreate() {
    if (this.$super && this.$super.beforeCreate) {
      this.$super.beforeCreate();
    }
    const templateOriginal = this.$options.template || '';
    this.$options.template = '<div class="container-adicional">' + templateOriginal + '</div>';
  },
};

Alternativamente, utilizar slots com funções oferece flexibilidade. O componente pai pode definir um slot que o componente filho sobrescreve com conteúdo específico.

No componente pai:

<template>
  <div class="estrutura-base">
    <slot name="area-conteudo" />
  </div>
</template>

No componente filho que estende:

<template slot="area-conteudo">
  <div>Conteúdo personalizado aqui</div>
</template>

<script>
import ComponentePai from './componente-pai.vue';

export default {
  extends: ComponentePai,
};
</script>

Modificar o template de um componente herdado pode introduzir complicações. O CSS pode perder alinhamento se a nova estrutura desrespeitar seletores existentes. Lógicas dependentes de elementos específicos podem falhar, como manipulação do DOM ou data binding. Eventos e escutas podem não disparar corretamente se a hierarquia for alterada. Slots modificados podem impedir a comunicação adequada entre componentes. Alterações estruturais também podem impactar o desempenho, forçando renderizações adicionais. Manutenção do código torna-se mais complexa, especialmente em equipes, devido à divergência em relação ao componente base.

Para evitar tais problemas, priorize técnicas como mixins, componentes compostos, props, eventos e slots com escopo. Essas abordagens mantêm a integridade e a encapsulamento do componente original.

Tags: Vue.js extends template Slots Mixins

Publicado em 7-16 08:00