[Vue.js] Accès à un élément de la DOM d’un composant enfant

Si vous développez avec Vue.js, vous avez peut-être eu, à un moment donné, besoin d’accéder à un élément de la DOM dans un composant enfant. En général, pour permettre la communication entre des composants parent et enfant, on utilise plutôt la liaison « double-sens » – ou 2-ways binding en anglais – à l’aide de la directive v-model ou bien encore des événements.

Cependant la méthode du 2-ways binding permet surtout de synchroniser des valeurs et de les garder à jour lorsque le parent doit y accéder. Ici, on aimerait pouvoir manipuler un élément de la DOM directement.

Vue.js: accès à un élément de la DOM d'un composant enfant

Nous allons utiliser les templates refs en combinaison avec la méthode defineExpose.

Template Refs

En Vue, les templates refs permettent de définir une référence sur un élément de la DOM afin d’y accéder dans le code une fois le composant monté (état mounted).

Avant l’apparition de la méthode useTemplateRef en Vue.js 3.5, il fallait, pour accéder à un élément, déclarer une ref du même nom que l’attribut utilisé sur l’élément ciblé.

Par exemple :

<template>
 <input ref="myInput"/>
</template>

Dans le script voici ce qu’on trouve alors :

const myInput = ref(null);

Avec la méthode useTemplateRef, on peut utiliser n’importe quel nom de variable puisqu’on mentionne le nom utilisé dans l’attribut en paramètre. Dans notre cas, cela va donner le code suivant.

import { useTemplateRef } from 'vue';

const input = useTemplateRef('myInput');

Voici le code de base de notre composant enfant, que nous appellerons MyInput.

<template>
	<input ref="myInput" />
</template>

<script setup>
import { useTemplateRef } from 'vue'; 
const input = useTemplateRef('myInput');
</script>

<style>
<!-- style rules here -->
</style>

En l’état il nous manque encore quelque chose pour accéder au champ depuis le parent.

defineExpose

Il est important de noter que le composant est considéré comme closed par défaut lorsqu’on utilise des composants type « SFC » – ce qui signifie Single-File Component – avec la syntaxe script setup.

Dans ce cas, si on veut accéder à des éléments de ce composant, il convient d’utiliser la méthode defineExpose. Elle prend en paramètre un objet qui regroupe les éléments à « exposer » aux autres composants.

Dans le script de MyInput, il faut alors rajouter :

defineExpose({
  input,
});

On va maintenant pouvoir accéder au champ depuis le parent.

<template>
	<MyInput ref="childComponent" />
</template>

<script>
import { useTemplateRef } from 'vue'; 
const child = useTemplateRef('childComponent');

function method() {
	console.log(child.value?.input);
}
</script>

<style>
<!-- style rules here -->
</style>

Dans le code du script parent on réutilise la méthode useTemplateRef afin de définir la ref pour le composant enfant. On pourra ainsi y accéder depuis différentes méthodes et effectuer des modifications sur l’élément en question, comme déclencher un événement (par exemple un clic), mettre à jour ou ajouter un attribut, interagir avec la valeur,…

Sources

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *