Diretivas Personalizadas
Introdução
Além do conjunto padrão de diretivas disponibilizadas no núcleo (tais como v-model
ou v-show
), a Vue também permite-te registar as tuas próprias diretivas personalizadas.
Nós introduzimos duas formas de reutilizar código na Vue: Componentes e Funções de Composição. Os componentes são os principais blocos do edifício, enquanto os constituíveis são focadas na reutilização da lógica com estado. As diretivas, por outro lado, são principalmente destinadas para a reutilização de lógica que envolve acesso de DOM de baixo nível sobre os elementos simples.
Uma diretiva personalizada é definida como um objeto contendo gatilhos de ciclo de vida semelhantes àqueles de um componente. Os gatilhos recebem o elemento em que a diretiva está vinculada. Cá está um exemplo de uma diretiva que foca em uma entrada quando o elemento é inserido no DOM pela Vue:
vue
<script setup>
// ativa "v-focus" nos modelos de marcação
const vFocus = {
mounted: (el) => el.focus()
}
</script>
<template>
<input v-focus />
</template>
Presumindo de que não tens clicado noutro lado na página, a entrada acima deveria ser auto-focada. Esta diretiva é mais útil do que o atributo autofocus
porque ela funciona não apenas sobre o carregamento da página - ele também funciona quando o elemento for dinamicamente inserido pela Vue.
No <script setup>
, qualquer variável em "camelCase" que começa com o prefixo v
pode ser utilizado como uma diretiva personalizada. No exemplo acima, vFocus
pode ser utilizado no modelo de marcação como v-focus
.
Se não estiveres a utilizar <script setup>
, as diretivas personalizadas podem ser registadas utilizando a opção directives
:
js
export default {
setup() {
/*...*/
},
directives: {
// ativa "v-focus" no modelo de marcação
focus: {
/* ... */
}
}
}
É também comum registar globalmente as diretivas personalizadas no nível de aplicação:
js
const app = createApp({})
// torna "v-focus" utilizável em todos os componentes
app.directive('focus', {
/* ... */
})
DICA
As diretivas personalizadas devem apenas ser utilizadas quando a funcionalidade desejada pode ser apenas alcançado através da manipulação direta do DOM. Prefira a marcação de modelos declarativa utilizando as diretivas embutidas tais como v-bind
quando possível porque elas são mais eficientes e amigáveis a interpretação no lado do servidor.
Gatilhos de Diretiva
Um objeto de definição de diretiva pode fornecer várias funções de gatilho (todas opcionais):
js
const myDirective = {
// chamada antes dos atributos do elemento serem vinculados
// ou antes dos ouvintes de evento serem aplicados
created(el, binding, vnode, prevVnode) {
// consulte abaixo os detalhes sobre os argumentos
},
// chamada bem antes do elemento ser inserido no DOM.
beforeMount() {},
// chamada quando o componente pai do elemento estiver vinculado
// e todos os seus filhos estiverem montados.
mounted() {},
// chamada antes do componente pai ser atualizado
beforeUpdate() {},
// chamada depois do componente pai e
// todos os seus filhos tiverem sido atualizados
updated() {},
// chamada antes do componente pai ser desmontado
beforeUnmount() {},
// chamada quando o componente pai estiver desmontado
unmounted() {}
}
Argumentos de Gatilho
Aos gatilhos de diretiva são passados estes argumentos:
el
: o elemento em que a diretiva está vinculada. Isto pode ser utilizado para manipular diretamente o DOM.binding
: um objeto contendo as seguintes propriedades.value
: O valor passado para a diretiva. Por exemplo emv-my-directive="1 + 1"
, o valor seria2
.oldValue
: O valor anterior, apenas disponível embeforeUpdate
eupdated
. Está disponível quer o valor tenha mudado ou não.arg
: O argumento passado para a diretiva, se houver. Por exemplo emv-my-directive:foo
, oarg
seria"foo"
.modifiers
: Um objeto contendo os modificadores, se houver. Por exemplov-my-directive.foo.bar
, o objeto de modificadores seria{ foo: true, bar: true }
.instance
: A instância do componente onde a diretiva é utilizada.dir
: O objeto de definição da diretiva.
vnode
: O nó de vue (VNode em Inglês) subjacente representando o elemento vinculado.prevNode
: O nó de vue (VNode em Inglês) representando o elemento vinculado da interpretação anterior. Apenas disponível os gatilhosbeforeUpdate
eupdated
.
Como um exemplo, considere a seguinte utilização de diretiva:
template
<div v-example:foo.bar="baz">
O argumento binding
(vinculação, em Português) seria um objeto na forma de:
js
{
arg: 'foo',
modifiers: { bar: true },
value: /* valor de `baz` */,
oldValue: /* valor de `baz` da atualização anterior */
}
Semelhante as diretivas embutidas, os argumentos de diretiva personalizada podem ser dinâmicos. Por exemplo:
template
<div v-example:[arg]="value"></div>
Aqui o argumento da diretiva será atualizado de maneira reativa baseada na propriedade arg
no nosso estado de componente.
NOTA
Para além de el
, deves tratar estes argumentos como de apenas-leitura e nunca modificá-los. Se precisares de partilhar a informação através dos gatilhos, é recomendado fazer isto através do atributo dataset do elemento.
Abreviação de Função
É comum para uma diretiva personalizada ter o mesmo comportamento para mounted
e updated
, sem precisar de outros gatilhos. Nestes casos podemos definir a diretiva como uma função:
template
<div v-color="color"></div>
js
app.directive('color', (el, binding) => {
// isto será chamado para ambos `mounted` e `updated`
el.style.color = binding.value
})
Literais de Objeto
Se a tua diretiva precisar de vários valores, podes também um literal de objeto de JavaScript. Lembra-te de que, as diretivas podem receber qualquer expressão de JavaScript válida.
template
<div v-demo="{ color: 'white', text: 'hello!' }"></div>
js
app.directive('demo', (el, binding) => {
console.log(binding.value.color) // => "white"
console.log(binding.value.text) // => "hello!"
})
Utilização sobre Componentes
Quando utilizadas sobre os componentes, as diretivas personalizadas sempre aplicar-se-ão à um nó de raiz do componente, semelhante aos Atributos Herdados.
template
<MyComponent v-demo="test" />
template
<!-- modelo de marcação de MyComponent -->
<div> <!-- a diretiva "v-demo" será aplicada aqui -->
<span>My component content</span>
</div>
Nota que os componentes podem potencialmente ter mais de um nó de raiz. Quando aplicada à um componente com vários nó de raiz, a diretiva será ignorada e um aviso será lançado. Ao contrário dos atributos, as diretivas não podem ser passadas para um elemento diferente com v-bind="$attrs"
. No geral, não é recomendado utilizar diretivas personalizadas sobre os componentes.