# Provide / inject

Cette page suppose que vous avez déjà lu les Principes de base des composants. Lisez-le d'abord si vous n'êtes pas familier avec les composants.

Habituellement, lorsque nous devons passer des données du composant parent au composant enfant, nous utilisons les props. Imaginez la structure dans laquelle vous avez des composants profondément imbriqués et vous n'avez besoin que de quelque chose du composant parent dans l'enfant profondément imbriqué. Dans ce cas, vous devez toujours faire passer la prop le long de la chaîne de composants, ce qui peut être gênant.

Pour de tels cas, nous pouvons utiliser la paire provide et inject. Les composants parents peuvent servir de fournisseur de dépendances pour tous ses enfants, quelle que soit la profondeur de la hiérarchie des composants. Cette fonctionnalité fonctionne en deux parties: le composant parent a une option provide pour fournir des données et le composant enfant a une optioninject pour commencer à utiliser ces données.

Provide/inject scheme

Par exemple, si nous avons une hiérarchie comme celle-ci:

Root
└─ TodoList
   ├─ TodoItem
   └─ TodoListFooter
      ├─ ClearTodosButton
      └─ TodoListStatistics
1
2
3
4
5
6

Si nous voulons passer la longueur des todo-items directement à TodoListStatistics, nous passerons la prop dans la hiérarchie: TodoList -> TodoListFooter -> TodoListStatistics. Avec l'approche provide/inject, nous pouvons le faire directement:

const app = Vue.createApp({})

app.component('todo-list', {
  data() {
    return {
      todos: ['Feed a cat', 'Buy tickets']
    }
  },
  provide: {
    user: 'John Doe'
  },
  template: `
    <div>
      {{ todos.length }}
      <!-- rest of the template -->
    </div>
  `
})

app.component('todo-list-statistics', {
  inject: ['user'],
  created() {
    console.log(`Injected property: ${this.user}`) // > Propriété injectée: John Doe
  }
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

Cependant, cela ne fonctionnera pas si nous essayons de fournir une propriété d'instance de composant ici:

app.component('todo-list', {
  data() {
    return {
      todos: ['Feed a cat', 'Buy tickets']
    }
  },
  provide: {
    todoLength: this.todos.length // cela entraînera l'erreur `Cannot read property 'length' of undefined`
  },
  template: `
    ...
  `
})
1
2
3
4
5
6
7
8
9
10
11
12
13

Pour accéder aux propriétés des instances de composants, nous devons convertir provide en une fonction renvoyant un objet

app.component('todo-list', {
  data() {
    return {
      todos: ['Feed a cat', 'Buy tickets']
    }
  },
  provide() {
    return {
      todoLength: this.todos.length
    }
  },
  template: `
    ...
  `
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

Cela nous permet de continuer à développer ce composant de manière plus sûre, sans craindre de changer/supprimer quelque chose sur lequel un composant enfant s'appuie. L'interface entre ces composants reste clairement définie, tout comme avec les props.

En fait, vous pouvez considérer l'injection de dépendances comme une sorte «de props à longue portée», excepté que:

  • les composants parents n'ont pas besoin de savoir quels descendants utilisent les propriétés qu'ils fournissent
  • les composants enfants n'ont pas besoin de savoir d'où proviennent les propriétés injectées

# Travailler avec la réactivité

Dans l'exemple ci-dessus, si nous modifions la liste de todos, ce changement ne sera pas reflété dans la propriététodoLength injectée. Ceci est dû au fait que les liaisons provide/inject ne sont pas réactives par défaut. Nous pouvons changer ce comportement en passant une propriété ref ou un objet reactive à provide. Dans notre cas, si nous voulions réagir aux changements dans le composant ancêtre, nous aurions besoin d'attribuer une propriété computed du Composition API à notre todoLength fournie:

app.component('todo-list', {
  // ...
  provide() {
    return {
      todoLength: Vue.computed(() => this.todos.length)
    }
  }
})

app.component('todo-list-statistics', {
  inject: ['todoLength'],
  created() {
    console.log(`Propriété injéctée: ${this.todoLength.value}`) // > Propriété injéctée: 5
  }
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

Dans ce cas, tout changement de todos.length sera correctement reflété dans les composants, où todoLength est injecté. En savoir plus sur computed dans la section Computed et Watch et reactive provide/inject dans la section du Composition API.

Deployed on Netlify.
Dernière Mise-à-jour: 3/19/2021, 8:08:18 PM