x-ref para crear referencias de elementos HTML en Alpine.js
Índice de contenido
- Qué es x-ref en Alpine.js y para qué sirve
- Cómo funciona $refs dentro de un componente Alpine
- Acceder al DOM sin querySelector
- Limitaciones importantes en Alpine v3
- Soluciones reales para múltiples referencias
- ✔ Opción 1 — Usar :x-ref dinámico dentro de x-for (solución elegante)
- ✔ Opción 2 — Usar querySelectorAll (fallback universal)
- ✔ Opción 3 — Mapear refs manualmente en init()
- Buenas prácticas al trabajar con x-ref
- Preguntas frecuentes sobre x-ref
- Conclusión
Cuando empecé a trabajar con Alpine.js, una de las primeras cosas que me llamó la atención fue lo parecida que era su forma de referenciar elementos al sistema de refs que ya había usado en Vue. La diferencia es que Alpine lo hace con un enfoque mucho más pequeño, simple y directo; perfecto para esos casos en los que no quiero montar toda una aplicación de Vue solo para resolver una interacción puntual.
Ya conocemos como emplear los condicionales y ciclos en Alpine JS, vamos ahora con otro tema.
Qué es x-ref en Alpine.js y para qué sirve
x-ref es la forma que Alpine.js ofrece para marcar un elemento del DOM y acceder a él dentro del componente sin usar document.querySelector ni IDs globales.
Es, literalmente, la versión ligera de ref en Vue.
<span x-ref="miTexto">Hola</span>
<button @click="$refs.miTexto.remove()">Eliminar</button>Que es equivalente a:
document.querySelector(".miTexto")Alpine expone automáticamente todas las referencias declaradas con x-ref dentro del objeto mágico $refs.
x-ref que nos permite tal cual indica su nombre de cierta forma referenciar un elemento html en otras palabras viene siendo lo mismo que colocar el document ElementById o querySelector o los 10 que existen en javascript:
Pero sería la forma de Alpine su uso es sencillo simplemente le colocamos una etiqueta es decir como si fuera el ID la clase el nombre un atributo personalizado lo que tú quieras y a partir de aquí lo referenciamos de la siguiente forma siempre recuerda que las referencias a los dólar son algo común en este tipo de frameworks:
<div x-data="{text:'Hello Alpine!'}">
<input type="text" x-model="text">
<p x-text="text"></p>
<span class="classExample" x-ref="textRef">Text Example</span>
<button @click="$refs.textRef.innerText=text">Click!</button>
<button @click="console.log($refs.textRef)">Click!</button>
</div>Cómo funciona $refs dentro de un componente Alpine
Cada vez que declaras una referencia, Alpine la indexa estrictamente por su nombre literal:
<span x-ref="title"></span>Acceso:
this.$refs.titleAlpine no interpreta ni evalúa ese nombre: si escribes "item.name" entonces la referencia se llamará literalmente "item.name".
Acceder al DOM sin querySelector
Una de las gracias de Alpine es que evita que tengas que escribir:
document.querySelector(".clase")Puedes manipular directamente:
this.$refs.title.textContent = "Nuevo título"Limitaciones importantes en Alpine v3
En Alpine v2 se podían crear refs dinámicamente dentro de loops.
En Alpine v3 esto no es posible.
Esto significa que si escribes:
<span x-ref="link[0]"></span>
<span x-ref="link[1]"></span>Alpine NO crea un array, ni interpreta link[0].
Crea dos refs llamadas literalmente:
"link[0]"
"link[1]"Y por eso:
console.log(this.$refs.link) // undefined
## Ejemplo básico de x-ref (estático y recomendado)
<div x-data="example">
<span x-ref="text">Hola</span>
<button @click="$refs.text.textContent = 'Cambiado'">Cambiar</button>
</div>
<script>
function example() {
return {
init() {
console.log(this.$refs.text) // <span>Hola</span>
}
}
}
</script>No importa lo que escribas dentro de x-ref="...", Alpine solo toma el valor como un string literal.
Soluciones reales para múltiples referencias
Aquí vienen las alternativas que sí funcionan en Alpine v3.
✔ Opción 1 — Usar :x-ref dinámico dentro de x-for (solución elegante)
Si necesitas refs dinámicos, declara el ref como binding:
<template x-for="(question, index) in questions">
<span :x-ref="'topic-' + question.id" x-text="question.text"></span>
</template>Ahora Alpine genera refs con nombres:
- "topic-1"
- "topic-2"
- etc.
Acceso:
this.$refs["topic-" + id].textContent = "Nuevo texto"✔ Opción 2 — Usar querySelectorAll (fallback universal)
Si quieres un array real:
let items = [...this.$root.querySelectorAll('[data-ref="item"]')]
items[0].textContent = "Primero"HTML:
<span data-ref="item">A</span>
<span data-ref="item">B</span>Es más “vanilla”, pero funciona siempre.
✔ Opción 3 — Mapear refs manualmente en init()
<span :x-ref="'link-' + index" x-for="(item, index) in items"></span>
init() {
this.links = Object.keys(this.$refs)
.filter(r => r.includes('link-'))
.map(r => this.$refs[r])
}Ahora this.links es un array real.
Otro ejemplo:
<ul x-data="quiz">
<template x-for="q in questions">
<li>
<span :x-ref="'topic-' + q.id" x-text="q.text"></span>
</li>
</template>
</ul>
<script>
function quiz() {
return {
questions: [
{ id: 1, text: "Pregunta 1" },
{ id: 2, text: "Pregunta 2" }
],
init() {
this.$refs["topic-1"].textContent = "Cambiado!"
}
}
}
</script>Buenas prácticas al trabajar con x-ref
- Cuándo usar Alpine vs Vue según mi experiencia
- Cuando solo necesito cambiar un texto, ocultar un menú o manipular un bloque pequeño, Alpine es lo ideal.
Justo esto fue lo que me convenció: puedo usar un patrón de refs similar a Vue, pero con un framework mucho más pequeño y sin configuración.
- Cuando solo necesito cambiar un texto, ocultar un menú o manipular un bloque pequeño, Alpine es lo ideal.
- Mantén Alpine simple
- Usa x-ref solo para manipulación puntual.
- Si necesitas estructuras complejas, usa IDs o clases.
- Evita depender de arrays de refs: Alpine no los soporta.
Preguntas frecuentes sobre x-ref
- ¿Cómo evitar undefined?
- No uses arrays dentro de x-ref.
- Asegúrate de que accedes al ref después de que Alpine haya montado (init() o $nextTick).
- ¿Cómo usar x-ref con x-for?
- Siempre con :x-ref="...":
- <span :x-ref="'item-' + index"></span>
- Diferencias entre Alpine v2 y v3
- v2: refs dinámicos sí funcionaban.
- v3: solo refs estáticos → más rápido, pero menos flexible.
Conclusión
x-ref es una herramienta sencilla pero poderosa de Alpine.js. Su comportamiento recuerda mucho al sistema de refs de Vue, algo que personalmente me hizo sentirme como en casa desde el primer día. Sin embargo, Alpine mantiene su filosofía minimalista: nada de arrays nativos de refs, nada de expresiones evaluadas dentro del atributo.
Si entiendes esta limitación y usas soluciones como :x-ref, IDs dinámicos o querySelectorAll, podrás trabajar con múltiples referencias sin problema.
Alpine sigue siendo para mí la opción perfecta cuando no quiero levantar toda una aplicación solo por manejar un par de interacciones en el DOM.
Siguiente paso, aprende a Persistir datos en el cliente con Alpine.js
Acepto recibir anuncios de interes sobre este Blog.
Aprende a usar la directiva x-ref en Alpine.js para acceder y manipular elementos del DOM de forma sencilla, evitando document.querySelector. Este tutorial cubre el uso de $refs, cómo crear referencias dinámicas dentro de x-for y las limitaciones importantes en Alpine v3.