Acceder a template refs con Vue 3 Composition API

Aprender a crear referencias para manipular elementos del DOM usando Vue 3 y la Composition API🔥


Aunque gracias a la reactividad de Vue puedes centrarte en el modelo (la información) de tu aplicación y dejar que él se encargue de mantener todo actualizado, en ocasiones necesitarás acceder al DOM para manipularlo. Para logarlo, tienes dos opciones: crear una directiva o acceder a través de referencias de plantilla (template refs).

Hoy exploraremos la segunda opción utilizando la Composition API, ya que el proceso es sensiblemente diferente a la Options API.

Crear un template ref

Para acceder a un elemento del DOM y manipularlo desde la instancia Vue, debes de crear una referencia reactiva con valor nulo, y luego asociarla al elemento que necesites con el atributo ref.

<script setup>
    import { ref, onMounted } from "vue"
    const formRef = ref(null)
</script>
<template>
    <form ref="formRef">...</form>
</template>

Acceder a un template ref

Con la referencia creada y asociada, podemos esperar a que el componente esté montado para acceder al interior del elemento DOM que tiene la referencia.

<script setup>
    ...
    onMounted(()=> {
        formRef.value.submit() // Enviamos el formulario
    })
</script>

Template refs y v-for

Un caso especial puede darse si quieres crear un template ref dentro de v-for. En esta situación debes crear una referencia reactiva con un array vacío (en lugar de null) y dejar que Vue actualice cada elemento con el valor del DOM adecuado.

<script setup>
    import { ref } from "vue"
    const items = ref([...])
    const itemsRef = ref([])
</script>
<template>
    <ul>
        <li ref="itemsRef"  v-for="item in items">...</li>
    </ul>
</template>

¿Para qué puedo necesitar algo así?, quizás te estés preguntando. Un escenario sería el uso de la Intersection Observer API: imagina que quieres ser notificado cuando el último item hace intersección con el viewport.

<script setup>
    ...
  
  const observer = new IntersectionObserver(entries => {
    entries.forEach(entry => {
      if (entry.isIntersecting()) {
        console.log("👋")
      }
    })
  })
  
  // Observamos el último item
  observer.observe(itemsRef[itemsRef.length - 1])
</script>

Resumiendo

Cuando necesites manipular directamente el DOM, crea una referencia reactiva y asóciala al elemento al que quieras acceder. Una vez se haya cargado tendrás todo lo que necesitas dentro de la nueva template ref.

Juan Andrés Núñez
Juan Andrés Núñez
Ingeniero Frontend. Especialista en Vue.js. Docente profesional. Estoico.