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.