Vue.js: Refs e DOM
Última atualização: 2026-10-20
As referências de modelo permitem que você acesse diretamente elementos do DOM ou instâncias de componentes filhos — por exemplo, chamando input.focus() ou acessando métodos de componentes. O Vue 3.5 introduziu a API de Composição useTemplateRef, mais poderosa, que funciona em conjunto com a inferência de tipos do TypeScript.
Os Template Refs são um “último recurso” — o Vue recomenda o uso de refs, reactive, props e emit para resolver a maioria dos problemas; os Template Refs só devem ser usados quando você precisar manipular diretamente o DOM ou uma instância de componente.
1. O que você vai aprender
ref="el"Noções básicas sobre referências a modelosuseTemplateRef(Recomendado para Vue 3.5+)- Acesso a elementos do DOM (foco, scrollIntoView, etc.)
- Acessando uma instância de um componente filho (usando o método
defineExpose) $refsSintaxe alternativa utilizando a API de composição- Matrizes de referência em
v-for - 5 principais casos de uso e 4 antipadrões
2. O dilema do “foco automático” em um formulário de login
(1) Problema: Como fazer com que o campo de entrada receba o foco automaticamente quando a janela modal for aberta?
Alice criou um modal de login que deveria colocar o foco automaticamente no campo de nome de usuário:
// ❌ The "Broken" Version:Directly querySelector
onMounted(() => {
const input = document.querySelector('.username-input')
input.focus() // ❌ Does not meet the requirements Vue Philosophy
})
A filosofia do Vue: evite a manipulação direta do DOM. Em vez disso, use Template Refs.
O gerente de produto Charlie:
“Alice, quando a janela modal abrir, o campo do nome de usuário deve receber o foco automaticamente para que os usuários possam começar a digitar imediatamente.”
(2) Solução para referências de modelos de visualização
(3) Receita
Após usar as referências de modelo:
- Legibilidade do código: Indique claramente “Quero referenciar este elemento”
- Está alinhado com a filosofia do Vue: não manipula diretamente o DOM
- Segurança de tipos: O TypeScript infere os tipos dos elementos
- Ciclo de vida correto: Acesso em
onMountedounextTick
3. Uso básico do ref
(1) Referência de string (estilo Vue 2, obsoleta)
// ❌ Not recommended:String ref
export default {
mounted() {
this.$refs.input.focus()
}
}
(2) A variável ref (recomendada no Vue 3)
(3) 5 Operações básicas
// 1. Visit DOM Element
inputRef.value // <input> Element
// 2. Call DOM API
inputRef.value.focus()
inputRef.value.blur()
inputRef.value.select()
inputRef.value.scrollIntoView()
// 3. Read/Edit DOM Properties
inputRef.value.value // input value
inputRef.value.disabled // disabled Properties
inputRef.value.style.color = 'red' // Edit Style
// 4. Monitoring DOM Events (Not recommended, use @event)
inputRef.value.addEventListener('focus', handler)
// 5. Accessing a Child Component Instance(For more details, see 17.4)
childRef.value.someMethod()
▶ Exemplo: Foco automático no formulário de login
▶ ExperimenteSaída:
Ao abrir a tela, o campo Usuário já está com o cursor (focus no onMounted).
Preencher alice / senha123 e enviar → console: Login: alice senha123.
Se o ref não existir no template, usernameRef.value seria null e o focus quebraria.
▶ Exemplo: Rolagem automática até o final da página
▶ ExperimenteSaída:
Chat vazio na primeira renderização.
Enviar "Oi" → a mensagem entra na lista, o campo é limpo e a caixa rola até ela.
Sem o await nextTick() a rolagem aconteceria antes do DOM receber o novo item.
4. useTemplateRef (Recomendado para Vue 3.5+)
(1) Por que o useTemplateRef é necessário?
A variável ref em <script setup> requer dois nomes (o modelo ref e a variável), o que pode facilmente levar a inconsistências. useTemplateRef lida com isso usando um único nome, e a inferência de tipos do TypeScript é mais poderosa.
(2) 5 principais vantagens
| Vantagem | Descrição |
|---|---|
| Inferência de tipo | O TypeScript reconhece automaticamente como um HTMLInputElement |
| Renomeação segura | Altere um nome em um único lugar; o IDE sincroniza a alteração |
| Como evitar incompatibilidades de nomes | Ocorrem erros quando as referências de modelo e os nomes das variáveis não coincidem |
| Configuração simplificada | Não é necessário o const inputRef = ref(null) |
| DevTools aprimoradas | Suporte ao Vue DevTools 5.x |
(3) Comparação completa
<!-- Old notation:Variable ref -->
<template>
<input ref="usernameInput">
</template>
<script setup>
import { ref, onMounted } from 'vue'
const inputRef = ref(null) // The name may not match the template.
onMounted(() => inputRef.value.focus())
</script>
<!-- New Writing Style:useTemplateRef(Vue 3.5+ Recommendations)-->
<template>
<input ref="usernameInput">
</template>
<script setup>
import { useTemplateRef, onMounted } from 'vue'
const inputRef = useTemplateRef('usernameInput') // One Name Does It All
onMounted(() => inputRef.value.focus())
</script>
5. Acessando uma instância de um componente filho
(1) defineExpose: Método Expose
(2) Acesso ao componente pai
<template>
<MyInput ref="myInputRef" v-model="searchQuery" />
<button @click="focusInput">Focus Input</button>
</template>
<script setup>
import { ref } from 'vue'
import MyInput from './MyInput.vue'
const searchQuery = ref('')
const myInputRef = ref(null)
function focusInput() {
myInputRef.value.focus() // Calling Methods Exposed by Child Components
myInputRef.value.select() // You can also use chained calls
}
</script>
(3) 5 principais casos de uso
| Cenário | Exposto pelo componente filho | Chamado pelo componente pai |
|---|---|---|
| Destaque do formulário | focus() |
inputRef.focus() |
| Limpar formulário | clear() |
formRef.clear() |
| Atualizar dados | reload() |
tableRef.reload() |
| Abrir janela pop-up | open() |
modalRef.open() |
| Enviar formulário | submit() |
formRef.submit() |
▶ Exemplo: Componente pai chamando um método de um componente filho
<!-- Child component:FormValidator.vue -->
<template>
<form>
<input v-model="email" placeholder="Email">
<input v-model="password" type="password" placeholder="Password">
</form>
</template>
<script setup>
import { ref } from 'vue'
const email = ref('')
const password = ref('')
const emailRef = ref(null)
const passwordRef = ref(null)
defineExpose({
validate: () => {
if (!email.value) {
emailRef.value.focus()
return false
}
if (!password.value || password.value.length < 6) {
passwordRef.value.focus()
return false
}
return true
},
reset: () => {
email.value = ''
password.value = ''
}
})
</script>
<!-- Parent Component:LoginPage.vue -->
<template>
<FormValidator ref="formRef" />
<button @click="submit">Submit</button>
</template>
<script setup>
import { ref } from 'vue'
import FormValidator from './FormValidator.vue'
const formRef = ref(null)
function submit() {
if (formRef.value.validate()) {
console.log('Valid!')
} else {
console.log('Invalid!')
}
}
</script>
Saída:
Clicar em Submit com os campos vazios: o foco vai para Email e o console mostra Invalid!.
Preencher email e senha (6+ caracteres) → console: Valid!.
reset() via defineExpose limpa os dois campos do filho.
6. A matriz ref em v-for
(1) Uso básico
(2) Referência dinâmica (v-for com contagem dinâmica)
(3) 5 pontos importantes a serem lembrados
| Pontos a serem observados | Descrição |
|---|---|
| Ordem da matriz | Corresponde à ordem dos dados no v-for |
| Reativo | Alterações na matriz ref exigem um observador |
| Renderização condicional | as referências podem não ser atualizadas após o v-if |
| Número de variáveis dinâmicas | Uso de referência a objeto ou função |
| Desempenho | Um grande número de referências (mais de 100) pode tornar a renderização mais lenta |
7. Exercício abrangente: tipagem de useTemplateRef no TypeScript
▶ Exemplo: Inferência de tipo para useTemplateRef
<template>
<input ref="usernameInput" type="text">
<MyChart ref="chartComponent" :data="chartData" />
</template>
<script setup lang="ts">
import { ref, useTemplateRef, onMounted } from 'vue'
import MyChart from './MyChart.vue'
// ✅ TypeScript Inference:HTMLInputElement | null
const usernameInput = useTemplateRef<HTMLInputElement>('usernameInput')
// ✅ TypeScript Inference:InstanceType<typeof MyChart> | null
const chartComponent = useTemplateRef<InstanceType<typeof MyChart>>('chartComponent')
onMounted(() => {
// usernameInput.value Automatic is HTMLInputElement
usernameInput.value?.focus()
// chartComponent.value "Auto" is a component instance
chartComponent.value?.refresh()
})
</script>
Saída:
Ao montar, o input recebe o foco e o gráfico executa refresh().
O TypeScript infere HTMLInputElement para o input e a instância de MyChart para o gráfico.
O encadeamento opcional evita erro quando a referência ainda não foi montada.
(1) 📊 5. Referência rápida para 5 erros comuns
| Erro | Sintoma | Solução |
|---|---|---|
| Erro ortográfico na referência do modelo | o valor da referência é nulo | Verifique se os nomes das referências correspondem |
Acesso no nível superior setup |
ref.value é nulo |
Use onMounted |
| Acesso dentro de uma janela pop-up | Não funciona | Use nextTick ou métodos DOM semelhantes |
| Acesso à matriz de referência no v-for | Desalinhamento de índices | Use :key para preservar a ordem |
| Referência entre componentes | indefinido | Os componentes filhos usam defineExpose |
(2) 📊 6. Comparação dos 5 principais tipos de referência
| Tipo | Exemplo | Aplicável a |
|---|---|---|
| Elemento DOM | ref="inputRef" → HTMLInputElement |
Acessar input/div |
| Instância do componente | ref="childRef" → Instância do componente |
Métodos do componente de tom |
| v-for array | ref="itemRefs" → Array |
Acessando itens da lista |
| Referência funcional | :ref="el => ..." → Elemento único |
Contagem dinâmica |
| Referência de string | ref="name" → this.$refs |
Estilo da Visualização 2 (não recomendado) |
❓ Perguntas Frequentes
useTemplateRef é obrigatório no Vue 3.5+?ref. É preferível usar a inferência de tipos do TypeScript.useRef (React)?useRef do React retorna uma ref mutável, enquanto a template ref do Vue retorna um objeto ref. O useTemplateRef do Vue 3.5+ possui uma API mais próxima da do useRef do React.v-for é atualizada?v-for é renderizada novamente. Também é atualizada quando v-if é ativada ou desativada. Você pode usar watch na matriz ref para responder às alterações.useTemplateRef<HTMLInputElement>('usernameInput'). Ou ref<HTMLInputElement | null>(null).📖 Resumo
- As referências de modelo são usadas para acessar diretamente elementos do DOM ou instâncias de componentes filhos
- 3 maneiras de escrever isso: referência de variável (Vue 3) / useTemplateRef (Vue 3.5+; recomendado) / referência de string (estilo Vue 2; não recomendado)
- 5 operações básicas: focar / rolar / selecionar / alterar propriedades / ajustar componentes
defineExposepermite que um componente filho exponha métodos ao seu pai- Em
v-for,refé automaticamente coletado em uma matriz - 5 cenários principais: Foco automático / Rolagem até o final da página / Método de ajuste de tom / Integração com aplicativos de terceiros / Medição do tamanho do elemento
- 4 antipadrões: erros ortográficos / acesso de nível superior / janelas pop-up que não utilizam
nextTick/ entre componentesref
📝 Exercícios
-
Questões básicas (Dificuldade: ⭐)
Implemente um formulário simples de foco automático:
- 1 campo de entrada + 1 botão
- O campo de entrada recebe o foco automaticamente após o carregamento da página
- Quando o botão é clicado, o texto do botão muda para “Enviado” e o botão fica desativado
-
Problemas avançados (Dificuldade: ⭐⭐)
Implementar uma janela de bate-papo que role automaticamente até o final da página:
- Lista de mensagens (contêiner div)
- Campo de entrada + botão “Enviar”
- Depois que uma mensagem é enviada, ela é adicionada à lista e a tela rola automaticamente até o final
- Use
v-forpara renderizar mensagens e uma matrizrefpara gerenciar o DOM
-
Problema desafiador (Dificuldade: ⭐⭐⭐)
Implementar um sistema completo de “componentes pai-filho + Template Refs”:
- Subcomponente FormValidator: disponibiliza os métodos validate() e reset()
- Componente pai da LoginPage: chama o método
validatepara realizar a validação; exibe uma mensagem de erro caso a validação falhe - 5 campos de preenchimento (nome de usuário/e-mail/senha/telefone/captcha)
- useTemplateRef (Vue 3.5+) + tipagem forte do TypeScript
- Colocar o foco automaticamente no primeiro campo de entrada quando a janela pop-up for aberta
- Quando ocorrer um erro, concentre-se no primeiro campo de erro