@@ -216,252 +112,86 @@ Vue.component('button-counter2', {
data: function () {
return buttonCounter2Data
},
- template: '
You clicked me {{ count }} times. '
+ template: '
Vous m\'avez cliquez {{ count }} fois. '
})
new Vue({ el: '#components-demo3' })
{% endraw %}
-### Composition de composants
-
-Les composants sont destinés à être utilisés ensemble, le plus souvent dans une relation parent-enfant : le composant A peut utiliser le composant B dans son propre template. Ils vont inévitablement avoir besoin de communiquer les uns avec les autres : le parent peut avoir besoin de passer des données à l'enfant, et l'enfant peut avoir besoin d'informer le parent que quelque chose s'est produit à l'intérieur. Cependant, il est également très important de garder le parent et l'enfant aussi découplés que possible via une interface clairement définie. Cela assure que le code de chaque composant puisse être écrit de manière relativement isolée, cela les rend plus maintenables et potentiellement plus simples à réutiliser.
-
-Dans Vue.js, la relation parent-enfant peut être résumée ainsi : **descente de props, remontée d'évènements**. Le parent passe les données à l'enfant via les **props**, et l'enfant envoie des messages à son parent via les **évènements**. Voyons comment cela fonctionne ci-dessous.
-
-Par exemple, vous pouvez avoir des composants pour un entête, une barre latérale et une zone de contenu, chacun contenant généralement d'autres composants pour les liens de navigation, les articles de blog, etc.
+## Organisation des composants
-Pour utiliser ces composants dans les templates, ils doivent être enregistrés afin que Vue les connaisse. Il existe deux types d'enregistrement de composants : **global** et **local**. Jusqu'à présent, nous avons seulement enregistré des composants globalement, en utilisant `Vue.component`:
+Il est commun pour une application d'être organisée en un arbre de composants imbriqués :
-### Passer des données avec props
+
-Chaque instance de composant a sa propre **portée isolée**. Cela signifie qu'on ne peut (et ne devrait) pas directement référencer des données du parent dans un template de composant enfant. Les données doivent être passées aux composants enfants en utilisant **props**.
+Par exemple, vous pouvez avoir des composants pour l'entête, la barre latérale, la zone de contenu ; chacun contenant lui aussi d'autres composants pour la navigation, les liens, les billets de blog, etc.
-Une prop est un attribut personnalisé permettant de passer des informations depuis des composants parents. Un composant enfant a besoin de déclarer explicitement quelles sont les props qu'il s'attend à recevoir en utilisant [l'option `props`](../api/#props) :
+Pour utiliser ces composants dans des templates, ils doivent être enregistrés pour que Vue les connaissent. Il y a deux types d'enregistrement de composant : **global** et **local**. Jusqu'ici, nous avons uniquement enregistré des composants globalement en utilisant `Vue.component` :
-``` js
-Vue.component('child', {
- // déclarer les props
- props: ['message'],
- // tout comme un élément de `data`, une prop peut être utilisée à l'intérieur de templates
- // et est également disponible dans l'instance via `this.message`
- template: '
{{ message }} '
+```js
+Vue.component('my-component-name', {
+ // ... options ...
})
```
-Alors nous pouvons lui passer une simple chaine de caractères comme suit :
-
-``` html
-
-```
+Les composants enregistrés globalement peuvent être utilisés dans le template de n'importe quelle instance racine de Vue (`new Vue`) créée après coup, ainsi que dans les sous-composants de l'arbre des composants de cette instance de Vue.
-Résultat :
+C'est tout ce que vous avez besoin de savoir à propos de l'enregistrement pour le moment, mais une fois que vous aurez fini de lire cette page et que vous vous sentirez à l'aise avec son contenu, nous vous recommandons de revenir pour lire le guide complet à propos de l'[Enregistrement de composant](components-registration.html).
-{% raw %}
-
-
-
-
-{% endraw %}
+## Passer des données aux composants enfants avec les props
-Les props sont des attributs personnalisés que vous pouvez sauvegarder dans un composant. Lorsqu'une valeur est transmise à un attribut prop, elle devient une propriété de cette instance de composant. Pour passer un titre à notre composant de blog, nous pouvons l'inclure dans la liste des props que ce composant accepte, en utilisant une propriété `props` :
+Plus tôt, nous avons mentionné la création d'un composant pour des billets de blog. Le problème est que ce composant ne sera utile que si l'on peut lui passer des données, comme le titre ou le contenu pour un billet spécifique à afficher. C'est ici que les props interviennent.
-Les attributs HTML sont insensibles à la casse, donc quand vous utilisez des templates qui ne sont pas des chaines de caractères, le nom de la prop en camelCase a besoin de son équivalent en kebab-case (délimité par des traits d'union) :
+Les props sont des attributs personnalisables que vous pouvez enregistrer dans un composant. Quand une valeur est passée à un attribut prop, elle devient une propriété de l'instance du composant. Pour passer un titre à notre billet de blog, nous devons l'inclure dans une liste de props que ce composant accepte, en utilisant l'option `props` :
-``` js
-Vue.component('child', {
- // camelCase en JavaScript
- props: ['myMessage'],
- template: '
{{ myMessage }} '
+```js
+Vue.component('blog-post', {
+ props: ['title'],
+ template: '
{{ title }} '
})
```
-``` html
-
-
-```
-
-Encore une fois, si vous utilisez les templates sous forme de chaine de caractères, ces limitations ne s'appliquent pas.
-
-### Props dynamiques
-
-Tout comme la liaison d'un attribut ordinaire avec une expression, nous pouvons aussi utiliser `v-bind` pour dynamiquement lier les props aux données de leurs parents. À chaque fois que les données sont mises à jour dans le parent, elles seront également mises à jour dans l'enfant :
-
-``` html
-
-
-
-
-
-```
-
-``` js
-new Vue({
- el: '#prop-example-2',
- data: {
- parentMsg: 'Message venant du parent'
- }
-})
-```
+Un composant peut avoir autant de props que vous le souhaitez et par défaut, n'importe quelle valeur peut être passée à une prop. Dans le template ci-dessus, vous devriez voir cette valeur dans l'instance du composant, comme pour `data`.
-Vous pouvez aussi utiliser la syntaxe abrégée pour `v-bind`:
+Une fois une prop enregistrée, vous pouvez lui passer des données en tant qu'attribut personnalisé comme ceci :
-``` html
-
+```html
+
+
+
```
-Résultat :
-
{% raw %}
-
-
-
+
+
+
{% endraw %}
-Si vous souhaitez passer toutes les propriétés dans un objet en tant que props, vous devez utiliser `v-bind` sans arguments (`v-bind` au lieu de `v-bind:prop-name`). Par exemple, avec un objet `todo` :
-
-``` js
-todo: {
- text: 'Apprendre Vue',
- isComplete: false
-}
-```
-
-Alors :
-
-``` html
-
-```
-
-Est équivalent à :
-
-``` html
-
-```
-
-### Littérale vs. Dynamique
-
-Une erreur répandue chez les débutants est d'essayer de passer un nombre en utilisant la syntaxe littérale :
-
-``` html
-
-
-```
-
-Cependant, puisque c'est une prop littérale, sa valeur est passée en tant que simple chaine de caractères `"1"` au lieu d'être un nombre. Si nous voulons passer un nombre JavaScript, nous avons besoin d'utiliser `v-bind` ainsi sa valeur est évaluée en tant qu'expression JavaScript :
-
-``` html
-
-
-```
-
-### Flux de données unidirectionnel
-
-Toutes les props forment une liaison **descendante unidirectionnelle** entre la propriété de l'enfant et celle du parent : quand la propriété parente est mise à jour, cela est signalé à l'enfant, mais pas dans l'autre sens. Cela empêche les composants enfants de modifier accidentellement l'état du parent, ce qui rendrait le flux de données de votre application difficile à appréhender.
-
-De plus, chaque fois que le composant parent est mis à jour, toutes les props dans le composant enfant vont être rafraichies avec les dernières valeurs. Cela signifie qu'il **ne** faut **pas** essayer de changer une prop à l'intérieur d'un composant enfant. Si vous le faites, Vue vous avertira dans la console.
-
-Il y a habituellement deux cas où il est tentant de changer une prop :
-
-1. La prop est utilisée uniquement pour passer une valeur d'initialisation. Le composant enfant veut simplement l'utiliser par la suite comme une propriété de donnée locale à partir de ce moment.
-
-2. La prop est passée comme une valeur brute qui doit être transformée.
-
-Les réponses correctes pour ces cas d'utilisation sont :
-
-1. Définir une propriété de donnée locale qui utilise la valeur initiale de la prop comme une valeur d'initialisation :
-
- ``` js
- props: ['initialCounter'],
- data: function () {
- return { counter: this.initialCounter }
- }
- ```
-
-2. Définir une propriété calculée qui est calculée à partir de la valeur de la prop :
-
- ``` js
- props: ['size'],
- computed: {
- normalizedSize: function () {
- return this.size.trim().toLowerCase()
- }
- }
- ```
-
-
Notez que les objets et tableaux en JavaScript sont passés par référence, aussi si la prop est un tableau ou un objet, modifier l'objet ou le tableau lui-même à l'intérieur de l'enfant **va** affecter l'état du parent.
-
-### Validation de prop
+Dans une application typique, cependant, vous préfèreriez avoir un tableau de billets dans `data` :
-Il est possible pour un composant de spécifier les conditions à remplir pour les props qu'il reçoit. Si une condition n'est pas satisfaite, Vue émettra des alertes. C'est particulièrement utile quand vous créez un composant qui a pour vocation d'être utilisé par d'autres.
-
-Au lieu de définir les props en tant que tableau de chaine de caractères, vous pouvez utiliser un objet avec des conditions de validation :
-
-``` js
-Vue.component('example', {
- props: {
- // vérification basique du type (`null` signifie l'acceptation de n'importe quel type)
- propA: Number,
- // plusieurs types possibles
- propB: [String, Number],
- // une chaine de caractères est obligatoire
- propC: {
- type: String,
- required: true
- },
- // un nombre avec une valeur par défaut
- propD: {
- type: Number,
- default: 100
- },
- // les objets et tableaux par défaut doivent être retournés
- // par une fabrique de fonctions
- propE: {
- type: Object,
- default: function () {
- return { message: 'hello' }
- }
- },
- // fonction de validation personnalisée
- propF: {
- validator: function (value) {
- return value > 10
- }
- }
+```js
+new Vue({
+ el: '#blog-post-demo',
+ data: {
+ posts: [
+ { id: 1, title: 'Mon initiation avec Vue' },
+ { id: 2, title: 'Blogger avec Vue' },
+ { id: 3, title: 'Pourquoi Vue est tellement cool' },
+ ]
}
})
```
-Le `type` peut être l'un des constructeurs natifs suivants :
+Maintenant, faisons le rendu d'un composant pour chacun :
```html
```
-De plus, `type` peut également être une fonction constructeur personnalisée et ainsi l'assertion sera faite avec une vérification `instanceof`.
+Vous voyez au-dessus que nous pouvons utiliser `v-bind` pour dynamiquement passer des props. Cela est particulièrement utile quand vous ne connaissez pas exactement le contenu dont vous êtes en train de faire le rendu à l'avance, comme dans le cas de [récupération de billets depuis une API](https://jsfiddle.net/chrisvfritz/sbLgr0ad).
-Quand une validation de prop échoue, Vue produira un avertissement dans la console (si vous utilisez le *build* de développement). Notez que cette props est validée __avant__ que l'instance du composant soit créée, donc à l'intérieur des fonctions `default` ou `validator`, les propriétés d'instance comme `data`, `computed`, ou `methods` ne seront pas disponibles.
+C'est tout ce que vous avez besoin de savoir à propos des props pour le moment, mais une fois que vous aurez fini de lire cette page et que vous vous sentirez à l'aise avec son contenu, nous vous recommandons de revenir pour lire le guide complet à propos des [props](components-props.html).
-## Attribut non-prop
+## Un élément racine unique
-Un attribut non-prop est un attribut qui est passé au composant, mais qui n'a pas de prop correspondante définie.
+Quand nous réalisons un composant `
`, votre template va éventuellement contenir plus que juste le titre :
-Bien que définir explicitement les props soit conseillé pour passer les informations à un composant enfant, les auteurs des bibliothèques de composant ne suivent pas forcément cette règle dans leurs composants. C'est pour cela que les composants peuvent accepter des attributs arbitraires, qui sont ajoutés à l'élément racine du composant.
-
-Par exemple, imaginez que nous utilisions un composant tiers `bs-date-input` avec un plugin Bootstrap qui nécessite un attribut `data-3d-date-picker` sur l'`input`. Nous pouvons ajouter cet attribut dans l'instance de notre composant :
-
-``` html
-
+```html
+{{ post.title }}
```
-Et l'attribut `data-3d-date-picker="true"` sera automatiquement ajouté à l'élément racine de `bs-date-input`.
+Vous allez au moins vouloir inclure le contenu du billet :
-## Remplacement et merge avec des attributs existants
-
-Imaginez que ceci est un template pour `bs-date-input`:
-
-``` html
-
+```html
+{{ post.title }}
+
```
-Pour ajouter un thème spécifique à notre plugin date picker, nous allons avoir besoin d'ajouter une classe, comme cela :
+Si vous essayez cela dans votre template cependant, Vue va afficher une erreur, expliquant que **tout composant doit avoir un unique élément racine**. Vous pouvez fixer cette erreur en imbriquant le template dans un élément parent comme :
```html
@@ -506,56 +229,13 @@ Pour ajouter un thème spécifique à notre plugin date picker, nous allons avoi
```
-Dans ce cas, deux valeurs différentes pour `class` sont définies :
-
-- `form-control`, qui est la classe du composant dans ce template
-- `date-picker-theme-dark`, qui est la classe passée au composant depuis son parent
-
-Pour la plupart des attributs, la valeur fournie au composant va remplacer la valeur mise initialement dans le composant. Donc par exemple, passer `type="large"` va remplacer `type="date"` et probablement le rendre inutilisable ! Heureusement, les attributs `class` et `style` sont plus malins, aussi les deux valeurs sont mergées, fournissant la valeur finale suivante : `form-control date-picker-theme-dark`.
-
-## Évènements personnalisés
-
-Nous avons appris que le parent peut passer des données à l'enfant en utilisant les props, mais comment allons-nous informer le parent quand quelque chose survient ? C'est là que le système d'évènement personnalisé de Vue entre en jeu.
+## Envoyer des messages aux parents avec les évènements
-### Utilisation de `v-on` avec les évènements personnalisés
-
-Chaque instance de Vue implémente une [interface d'évènements](../api/#Instance-Methods-Events), cela signifie qu'elle peut :
-
-- Écouter un évènement en utilisant `$on(eventName)`
-- Déclencher un évènement en utilisant `$emit(eventName, optionalPayload)`
-
-Notez que le système d'évènement de Vue est différent de celui de l'API navigateur [EventTarget](https://developer.mozilla.org/fr/docs/Web/API/EventTarget). Bien qu'il fonctionne de manière similaire, `$on` et `$emit` __ne__ sont __pas__ des alias pour `addEventListener` et `dispatchEvent`.
-
-De plus, un composant parent peut écouter des évènements émis depuis un composant enfant en utilisant `v-on` directement sur le template où le composant enfant est utilisé.
-
-Vous ne pouvez pas utiliser `$on` pour écouter les évènements émis par les enfants. Vous devez utiliser `v-on` directement dans le template, comme dans l'exemple ci-dessous.
-
-Voici un exemple :
-
-``` html
-
-```
+Lors de notre développement du composant ``, plusieurs fonctionnalités vont demander de communiquer des informations au parent. Par exemple, nous pourrions décider d'inclure une fonctionnalité d'accessibilité pour élargir le texte du billet de blog, alors que le reste de la page resterait dans sa taille par défaut :
-``` js
-Vue.component('button-counter', {
- template: '{{ counter }} ',
- data: function () {
- return {
- counter: 0
- }
- },
- methods: {
- incrementCounter: function () {
- this.counter += 1
- this.$emit('increment')
- }
- },
-})
+Dans le parent, nous pouvons supporter cette fonctionnalité en ajoutant une propriété de donnée `postFontSize` :
+```js
new Vue({
el: '#blog-posts-events-demo',
data: {
@@ -565,36 +245,21 @@ new Vue({
})
```
-Which can be used in the template to control the font size of all blog posts:
+Qui pourrait être utilisé dans un template pour contrôler la taille de la police de tous les billets de blog :
-Dans cet exemple, il est important de noter que le composant enfant est toujours complètement découplé de ce qui se passe en dehors de celui-ci. Tout ce qu'il fait, c'est rapporter des informations sur sa propre activité, juste au cas où le composant parent écouterait.
-
-Voici comment utiliser des données complémentaires :
-
-``` html
-
-
{{ msg }}
-
+```html
+
```
-``` js
-Vue.component('button-message', {
- template: `
-
- Envoyer
-
`,
- data: function () {
- return {
- message: 'message test'
- }
- },
- methods: {
- handleSendMessage: function () {
- this.$emit('message', { message: this.message })
- }
- }
-})
+Maintenant, ajoutons un bouton pour élargir le texte juste avant le contenu de chaque billet :
```js
Vue.component('blog-post', {
@@ -611,164 +276,31 @@ Vue.component('blog-post', {
})
```
-{% raw %}
-
-
-{% endraw %}
-
-Dans le second exemple, il est important de noter que le composant enfant est toujours complètement découplé de ce qu'il peut se passer à l'extérieur. Tout ce qu'il fait c'est reporter l'information à propos de sa propre activité en incluant les données utiles dans le déclencheur d'évènement, au cas où le composant parant en aurait besoin.
+
L'exemple ci-dessus et plusieurs exemples futurs utilisent une chaine de caractère JavaScript appelée [modèles de libellés](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals) permettant des templates multilignes plus lisibles. Ceux-ci ne sont pas supportés dans Internet Explorer (IE), aussi, si vous souhaitez supporter IE sans utiliser de transpilleur (p. ex. Babel ou TypeScript), [échappez le caractère de nouvelle ligne](https://css-tricks.com/snippets/javascript/multiline-string-variables-in-javascript) à la place.
-### Lier des évènements natifs aux composants
+Le problème est que le bouton ne fait rien du tout :
-Il y a des fois où vous souhaitez écouter un évènement natif sur l'élément racine d'un composant. Dans ce cas, vous devez utiliser le modificateur `.native` sur `v-on`. Par exemple :
-
-``` html
-
+```html
+
+ Élargir le texte
+
```
-### Modificateur `.sync`
-
-> 2.3.0+
-
-Dans certains cas, nous pourrions avoir besoin d'une « liaison bidirectionnelle » pour une prop. En fait, dans Vue 1.x, c'est exactement ce que le modificateur `.sync` permettait. Quand un composant enfant mute une prop qui a `.sync`, la valeur est remontée au parent. C'est pratique, cependant cela peut conduire à des soucis de maintenance sur le long terme car cela brise l'hypothèse du flux de donnée unidirectionnelle : le code qui mute dans des props enfants affecte l'état du parent.
-
-C'est pour cela que nous avions retiré le modificateur `.sync` dans la version 2.0. Cependant, nous trouvons tout de même qu'il existe des cas où celle-ci est très utile, notamment pour les composants réutilisables. Ce dont nous avions besoin était **de rendre le code d'un enfant qui affecte l'état d'un parent plus cohérent et explicite.**
+Quand nous cliquons sur le bouton, nous avons besoin de communiquer au parent qu'il devrait élargir le texte de tous les billets. Heureusement, l'instance de Vue fournit un système d'évènements personnalisables pour résoudre ce problème. Pour émettre un évènement au parent, nous devons appeler la [méthode préconçue **`$emit`**](../api/#Methodes-et-Evenements-d’Instance), en lui passant le nom de l'évènement :
-Dans la 2.3.0+ nous réintroduisons donc le modificateur `.sync` pour les props, mais cette fois, ce n'est qu'un sucre syntaxique pour étendre automatiquement un écouteur `v-on` additionnel :
+```html
+
+ Élargir le texte
+
+```
-Ce qui suit
+Quand nous somme sur notre billet de blog, nous pouvons écouter cet évènement avec `v-on`, exactement comme nous le ferrions avec un évènement natif du DOM :
-``` html
-
-```
-
-est le raccourci de :
-
-``` html
-
bar = val">
-```
-
-Pour un composant enfant qui met à jour la valeur de `foo`, il faut explicitement émettre un évènement au lieu de muter la prop :
-
-``` js
-this.$emit('update:foo', newValue)
-```
-
-Le modificateur `.sync` peut aussi être utilisé avec `v-bind` quand il utilise un objet pour affecter plusieurs propriétés en une seule fois :
-
-```html
-
-```
-
-Cela a pour effet d'ajouter des écouteurs de mise à jour `v-on` sur `foo` et `bar`.
-
-### Composants de champ de formulaire utilisant les évènements personnalisés
-
-Les évènements personnalisés peuvent aussi être utilisés pour créer des champs personnalisés qui fonctionnent avec `v-model`. Rappelez-vous :
-
-``` html
-
-```
-
-est juste du sucre syntaxique pour :
-
-``` html
-
-```
-
-Quand il est utilisé avec un composant, cela peut être simplifié par :
-
-``` html
-
{ something = value }">
-
-```
-
-Donc pour qu'un composant fonctionne avec `v-model`, il doit :
-
-- accepter une `value` prop
-- émettre un évènement `input` avec la nouvelle valeur.
-
-Voyons cela par l'exemple avec une simple saisie de devise :
-
-``` html
-
-```
-
-``` js
-Vue.component('currency-input', {
- template: '\
-
\
- $\
- \
- \
- ',
- props: ['value'],
- methods: {
- // Au lieu de mettre à jour directement la valeur, cette
- // méthode est utilisée pour formater et mettre des
- // contraintes sur la valeur en entrée
- updateValue: function (value) {
- var formattedValue = value
- // Retirer les espaces de part et d'autre
- .trim()
- // Tronquer à deux chiffres après la virgule
- .slice(
- 0,
- value.indexOf('.') === -1
- ? value.length
- : value.indexOf('.') + 3
- )
- // Si la valeur n'est pas déjà dans le bon format,
- // la réécrire manuellement pour qu'elle le soit
- if (formattedValue !== value) {
- this.$refs.input.value = formattedValue
- }
- // Émettre la valeur du nombre à travers l'évènement input
- this.$emit('input', Number(formattedValue))
- }
- }
-})
+```html
+
```
{% raw %}
@@ -789,7 +321,7 @@ Vue.component('blog-post', {
\
{{ post.title }} \
\
- Enlarge text\
+ Élargir le texte\
\
\
\
@@ -799,9 +331,9 @@ new Vue({
el: '#blog-posts-events-demo',
data: {
posts: [
- { id: 1, title: 'My journey with Vue', content: '...content...' },
- { id: 2, title: 'Blogging with Vue', content: '...content...' },
- { id: 3, title: 'Why Vue is so fun', content: '...content...' }
+ { id: 1, title: 'Mon initiation avec Vue', content: '...content...' },
+ { id: 2, title: 'Blogger avec Vue', content: '...content...' },
+ { id: 3, title: 'Pourquoi Vue est tellement cool', content: '...content...' }
],
postFontSize: 1
}
@@ -809,434 +341,176 @@ new Vue({
{% endraw %}
-L'implémentation ci-dessus est plutôt naïve cependant. Par exemple, les utilisateurs peuvent toujours saisir plusieurs points et même parfois des lettres (beurk) ! Donc pour ceux qui souhaiteraient voir un exemple non trivial, voici un filtre de devise plus robuste :
-
-It's sometimes useful to emit a specific value with an event. For example, we may want the `
` component to be in charge of how much to enlarge the text by. In those cases, we can use `$emit`'s 2nd parameter to provide this value:
-
-### Personnalisation de composant avec `v-model`
-
-> Nouveau dans la 2.2.0+
-
-Par défaut, `v-model` sur un composant utilise `value` en tant que prop et `input` en tant qu'évènement, mais plusieurs types de champ comme les cases à cocher et les boutons radio pourraient utiliser `value` pour un usage différent. Utiliser l'option `model` permet d'éviter les conflits dans ce genre de situations :
-
-``` js
-Vue.component('my-checkbox', {
- model: {
- prop: 'checked',
- event: 'change'
- },
- props: {
- checked: Boolean,
- // ceci permet d'utiliser la prop `value` pour un usage différent
- value: String
- },
- // ...
-})
-```
-
-``` html
-
-```
-
-La partie ci-dessus sera équivalente à :
-
-``` html
- { foo = val }"
- value="une valeur">
-
-```
-
-Notez que vous devez encore déclarer la prop `checked` explicitement.
-
-### Communication non parent-enfant
-
-Parfois deux composants peuvent avoir besoin de communiquer entre eux mais ne sont pas parent et enfant l'un de l'autre. Dans les scénarios simples, vous pouvez utiliser une instance de Vue vide comme canal d'évènements central.
-
-``` js
-var bus = new Vue()
-```
-``` js
-// dans la méthode du composant A
-bus.$emit('id-selected', 1)
-```
-``` js
-// dans le hook de création de B
-bus.$on('id-selected', function (id) {
- // ...
-})
-```
-
-Dans des cas plus complexes, vous pouvez envisager l'utilisation d'un [*pattern* de management d'état](state-management.html).
+### Émettre une valeur avec un évènement
-## Distribution de contenu avec des slots
+Il est parfois utile d'émettre une valeur spécifique avec un évènement. Par exemple, nous pourrions vouloir que le composant `` soit en charge de comment élargir le texte. Dans ce cas, nous pouvons utiliser `$emit` en second paramètre pour fournir cette valeur :
-Quand on utilise des composants, il est souvent souhaitable de les composer comme ceci :
-
-``` html
-
-
-
-
+```html
+
+ Élargir le texte
+
```
-Il y a deux choses à noter ici :
-
-1. Le composant `` ne sait pas quel contenu il va recevoir. Ceci est défini par le composant qui utilise ``.
-
-2. Le composant `` a vraisemblablement son propre template.
+Puis quand nous écoutons l'évènement dans le parent, nous pouvons accéder à la valeur de l'évènement émise avec `$event` :
-Pour faire fonctionner la composition, nous avons besoin d'un moyen pour entremêler le « contenu » du parent et le template de son propre composant. C'est un processus appelé **distribution de contenu** (ou « transclusion » si vous êtes familier avec Angular). Vue.js implémente une API de distribution de contenu modélisée à partir du [brouillon de spécification sur les Web Components](https://github.com/w3c/webcomponents/blob/gh-pages/proposals/Slots-Proposal.md), en utilisant l'élément spécial `` pour servir de points de distribution pour le contenu original.
-
-### Portée de compilation
-
-Avant de rentrer plus profondément dans l'API, clarifions dans quelle portée le contenu va être compilé. Imaginez un template comme celui-ci :
-
-``` html
-
- {{ message }}
-
+```html
+
```
-`message` devrait-il être lié aux données du parent ou aux données de l'enfant ? La réponse est : au parent. Une règle simple pour la portée du composant est :
-
-> Tout ce qui se trouve dans le template parent est compilé dans la portée du parent ; tout ce qui se trouve dans le template enfant est compilé dans la portée de l'enfant.
-
-Une erreur répandue est d'essayer de lier une directive à une propriété/méthode enfant dans le template du parent :
+Ou, si le gestionnaire d'évènement est une méthode :
-``` html
-
-
+```html
+
```
-En admettant que `someChildProperty` est une propriété du composant enfant, l'exemple ci-dessus ne fonctionnerait pas. Le template parent n'est pas au courant de l'état du composant enfant.
-
-Si vous avez besoin de lier des directives enfants sur un composant du nœud racine, vous devriez faire cela sur le template du composant enfant :
+Puis la valeur sera fournie en tant que premier argument de cette méthode :
-``` js
-Vue.component('child-component', {
- // ceci fonctionne, car nous sommes dans la bonne portée
- template: 'Enfant
',
- data: function () {
- return {
- someChildProperty: true
- }
+```js
+methods: {
+ onEnlargeText: function (enlargeAmount) {
+ this.postFontSize += enlargeAmount
}
}
```
-De façon similaire, le contenu distribué sera compilé dans la portée parente.
-
-### Slot unique
-
-Le contenu parent sera **évincé** si le template du composant enfant contient au moins une balise ``. Quand il n'y a qu'un seul slot sans attribut, tout le fragment de contenu sera inséré à sa position dans le DOM, remplaçant le slot lui-même.
+### Utiliser `v-model` sur les composants
-Tout ce qui était contenu à la base dans les balises `` est considéré comme **du contenu par défaut**. Le contenu par défaut est compilé dans la portée enfant et ne sera affiché que si l'élément l'incluant est vide et qu'il n'y a pas de contenu à insérer.
+Les évènements personnalisés peuvent aussi être utilisés pour créer des champs qui fonctionnent avec `v-model`. Rappelez-vous cela :
-Supposons que nous ayons un composant appelé `my-component` avec le template suivant :
-
-``` html
-
-
Je suis le titre de l'enfant
-
- Ceci ne sera affiché que s'il n'y a pas de contenu
- à distribuer.
-
-
-```
-
-Et un parent qui utilise le composant :
-
-``` html
-
-
Je suis le titre du parent
-
- Ceci est le contenu original
- Ceci est encore du contenu original
-
-
+```html
+
```
-Le résultat du rendu sera :
+réalise la même chose que :
-``` html
-
-
Je suis le titre du parent
-
-
Je suis le titre de l'enfant
-
Ceci est le contenu original
-
Ceci est encore du contenu original
-
-
+```html
+
```
-### Slots nommés
-
-Les éléments `` ont un attribut spécial, `name`, qui peut être utilisé pour personnaliser la façon dont le contenu doit être distribué. Vous pouvez avoir de multiples slots avec des noms différents. Un slot nommé ira avec n'importe quel élément possédant l'attribut `slot` correspondant dans le fragment de contenu.
-
-Il peut encore y avoir un slot non nommé, c'est le **slot par défaut** qui va servir de fourretout pour tout le contenu ne concordant avec aucun nom. S'il n'y a pas de slot par défaut, le contenu ne concordant pas est évincé.
-
-Par exemple, avec un composant `app-layout` avec le template suivant :
+Quand il est utilisé sur un composant, `v-model` fait plutôt cela :
``` html
-
-
-
-
-
-
-
+
```
-Le balisage du parent :
+Pour que cela puisse fonctionner, la balise ` ` à l'intérieur du composant doit :
-``` html
-
- Voici un titre de page
+- Lier l'attribut `value` à la prop `value`
+- Et sur l'`input`, émettre son propre évènement personnalisé `input` avec la nouvelle valeur
- Un paragraphe pour le contenu principal.
- Et un autre.
+Voici un exemple en action :
- Ici plusieurs informations de contact
-
+```js
+Vue.component('custom-input', {
+ props: ['value'],
+ template: `
+
+ `
+})
```
-Le résultat du rendu sera :
+Maintenant `v-model` fonctionnera parfaitement avec le composant :
-``` html
-
-
- Voici un titre de page
-
-
- Un paragraphe pour le contenu principal.
- Et un autre.
-
-
-
+```html
+
```
-L'API de distribution de contenu est un mécanisme vraiment utile lors de la conception de composants qui sont censés être composés ensemble.
-
-### Slots avec portée
-
-> Nouveau dans la 2.1.0+
+C'est tout ce que vous avez besoin de savoir à propos des évènements pour le moment, mais une fois que vous aurez fini de lire cette page et que vous vous sentirez à l'aise avec son contenu, nous vous recommandons de revenir pour lire le guide complet à propos des [évènements personnalisés](components-custom-events.html).
-Un slot avec portée est un type de slot spécial qui fonctionne comme un template réutilisable (auquel on peut passer des données) au lieu d'éléments déjà rendus.
+## Distribution de contenu avec les slots
-Dans un composant enfant, passez simplement les données via le slot de la même manière que vous passeriez des props dans un composant :
+Exactement comme les éléments HTML, il est souvent utile de passer du contenu à un composant comme ceci :
``` html
-
-
-
-```
-
-Dans le parent, un élément `` avec un attribut spécial `slot-scope` indique que c'est un template pour un slot avec portée. La valeur de `slot-scope` est le nom de la variable temporaire qui contient l'objet des props passé à l'enfant :
-
-``` html
-
-
-
- bonjour du parent
- {{ props.text }}
-
-
-
+
+ Quelque chose c'est mal passé.
+
```
-Si nous faisons le rendu de ce qui précède, la sortie sera :
+Qui pourrait faire le rendu de quelque chose comme :
-``` html
-
-
- bonjour du parent
- bonjour de l'enfant
-
+{% raw %}
+
+
+ Quelque chose c'est mal passé.
+
-```
-
-> Dans la 2.5.0+, `slot-scope` n'est plus limité à `
` et peut-être utilisé avec n'importe quel élément ou composant.
-
-Un cas d'utilisation plus typique des slots avec portée serait un composant de liste qui permettrait à l'utilisateur du composant de personnaliser la manière de faire le rendu de chaque élément de la liste :
-
-``` html
-
-
-
- {{ props.text }}
-
-
-```
-
-Et le template pour le composant de liste :
-
-``` html
-
-```
-
-#### Destructuration
-
-La valeur de `slot-scope` est en fait une expression JavaScript valide qui apparait à la position d'un argument dans la déclaration d'une fonction. Cela signifie que sur les environnements supportés (dans les composants monofichiers ou dans les navigateurs modernes) vous pouvez aussi utiliser la destructuration ES2015 dans une expression :
-
-``` html
-
- {{ text }}
-
-```
-
-## Composants dynamiques
-
-Vous pouvez utiliser le même point de montage et dynamiquement permuter entre de multiples composants en utilisant l'élément réservé `` et en les liant dynamiquement à son attribut `is` :
-
-``` js
-var vm = new Vue({
- el: '#example',
- data: {
- currentView: 'home'
- },
- components: {
- home: { /* ... */ },
- posts: { /* ... */ },
- archive: { /* ... */ }
- }
+
+
{% endraw %}
-Fortunately, this task is made very simple by Vue's custom `` element:
-
-### `keep-alive`
-
-Si vous voulez garder en mémoire les composants à enlever et ainsi préserver son état ou éviter d'en faire le rendu à nouveau, vous pouvez encapsuler un composant dynamique dans un élément `` :
-
-``` html
-
-
-
-
-
-```
-
-Obtenez plus de détails sur `` dans la [référence de l'API](../api/#keep-alive).
-
-## Divers
-
-### Création de composants réutilisables
-
-Lors de la création de composants, il est bon de garder à l’esprit que vous avez l’intention plus tard de les réutiliser ailleurs. Il est acceptable que les composants utilisés qu'une seule fois soient fortement couplés, mais des composants réutilisables doivent définir une interface publique claire et n'émettre aucune hypothèse sur le contexte dans lequel ils sont utilisés.
+Heureusement, cette tâche est vraiment simple avec l'élément personnalisé `` de Vue :
-L'API pour les composants de Vue se découpe en trois parties : les props, les évènements et les slots :
-
-- Les **props** permettent à l'environnement extérieur de passer des données dans le composant
-
-- Les **évènements** permettent au composant de déclencher des effets de bord dans l'environnement extérieur
-
-- Les **slots** permettent à l'environnement extérieur de composer le composant avec du contenu additionnel.
-
-les syntaxes abrégées dédiées à `v-bind` et `v-on`, l'intention peut être clairement et succinctement communiquée dans le template :
-
-``` html
-
-
- Hello!
-
-```
-
-### Les refs des composants enfants
-
-Malgré l'existence des props et des évènements, parfois vous aurez toujours besoin d'accéder directement à un composant enfant en JavaScript. Pour parvenir à cela vous pouvez assigner un ID de référence au composant enfant en utilisant `ref`. Par exemple :
-
-``` html
-
-
-
-```
-
-``` js
-var parent = new Vue({ el: '#parent' })
-// accès au composant enfant
-var child = parent.$refs.profile
-```
-
-Quand `ref` est utilisé conjointement avec `v-for`, la référence que vous obtenez sera un tableau ou un objet contenant les composants enfants reflétant la source de donnée.
-
-Les `$refs` sont seulement renseignées après le rendu du composant, et ne sont pas réactives. Elles sont seulement destinées à servir de porte dérobée pour la manipulation directe d'enfant (vous devriez éviter d'utiliser `$refs` dans vos templates et propriétés calculées).
-
-### Composants asynchrones
-
-Dans de grosses applications, nous avons parfois besoin de diviser la structure en de plus petits fragments et uniquement charger le composant depuis le serveur quand c'est vraiment nécessaire. Pour rendre ça plus simple, Vue permet de définir votre composant comme une fabrique de fonctions qui résoudra de manière asynchrone la définition de votre composant. Vue déclenchera la fabrique de fonctions uniquement lorsque le rendu du composant est vraiment nécessaire sur le composant et mettra ce rendu en cache pour le resservir lors de futures demandes de rendu. Par exemple :
-
-``` js
-Vue.component('async-example', function (resolve, reject) {
- setTimeout(function () {
- // Passer la définition du composant à la fonction de rappel `resolve`
- resolve({
- template: 'I am async!
'
- })
- }, 1000)
+```js
+Vue.component('alert-box', {
+ template: `
+
+ Erreur !
+
+
+ `
})
```
-La fabrique de fonctions reçoit une fonction de rappel `resolve` qui devra être appelée quand vous aurez récupéré la définition de votre composant depuis le serveur. Vous pouvez également appeler `reject(reason)` pour indiquer que le chargement a échoué. La fonction `setTimeout` est simplement là en tant qu'exemple ; la manière de récupérer le composant est entièrement à votre charge. Une approche recommandée est d'utiliser les composants asynchrones conjointement avec [la fonctionnalité de scission de code de webpack](https://webpack.js.org/guides/code-splitting-require/) :
-
-``` js
-Vue.component('async-webpack-example', function (resolve) {
- // Cette syntaxe de `require` va indiquer à webpack
- // de découper automatiquement votre code après build dans
- // des paquetages (« bundles ») qui seront chargés par des requêtes Ajax.
- require(['./my-async-component'], resolve)
-})
-```
+Comme vous pouvez le constater plus haut, nous avons seulement ajouté un slot là où nous souhaitions faire atterrir le contenu - et c'est tout. C'est fait !
-Vous pouvez également retourner une `Promise` (promesse) dans la fabrique de fonctions ainsi avec webpack 2 et la syntaxe ES2015 vous pouvez faire :
+C'est tout ce que vous avez besoin de savoir à propos des slots pour le moment, mais une fois que vous aurez fini de lire cette page et que vous vous sentirez à l'aise avec son contenu, nous vous recommandons de revenir plus tard pour lire le guide complet à propos des [slots](components-slots.html).
-``` js
-Vue.component(
- 'async-webpack-example',
- // La fonction `import` retourne un objet `Promise`.
- () => import('./my-async-component')
-)
-```
+## Composants dynamiques
-Quand vous utilisez une [inscription locale](components.html#Local-Registration), vous pouvez également fournir une fonction qui retourne une `Promise` :
+Parfois, il est utile de dynamiquement interchanger des composants, comme dans une interface à onglet :
-``` js
+{% raw %}
+
+
+ {{ tab }}
+
+
+
+
+
{% endraw %}
-The above is made possible by Vue's `` element with the `is` special attribute:
+Ce qu'il y a ci-dessus est rendu possible grâce à l'élément `` de Vue avec l'attribut spécial `is` :
```html
```
-Cela signifie que la PascalCase est la _convention de déclaration_ la plus universelle et que la kebab-case est la _convention d'utilisation_ la plus universelle.
-
-Si votre composant ne passe pas de contenu via des éléments `slot` vous pouvez même utiliser la syntaxe d'autofermeture `/` après le nom :
+Dans l'exemple ci-dessus, `currentTabComponent` peut contenir soit :
-See [this fiddle](https://jsfiddle.net/chrisvfritz/o3nycadu/) to experiment with the full code, or [this version](https://jsfiddle.net/chrisvfritz/b2qj69o1/) for an example binding to a component's options object, instead of its registered name.
-
-Encore une fois, cela fonctionne _seulement_ dans les templates sous forme de chaine de caractères. Les éléments autofermants ne sont pas du HTML valide et l'analyseur HTML natif de votre navigateur ne le comprendra pas.
-
-### Composants récursifs
-
-Les composants peuvent s'invoquer récursivement dans leur propre template. Cependant, ils peuvent uniquement le faire avec l'option `name` :
-
-This will lead to issues when using components with elements that have such restrictions. For example:
-
-Quand vous inscrivez un composant de manière globale en utilisant `Vue.component`, l'ID global est automatiquement défini en tant qu'option `name` du composant.
-
-``` js
-Vue.component('unique-name-of-my-component', {
- // ...
-})
-```
+- le nom du composant enregistré, ou
+- un objet d'option de composant
-Si vous n'êtes pas prudent, les composants récursifs peuvent conduire à des boucles infinies :
+Regardez [ce fiddle](https://jsfiddle.net/chrisvfritz/o3nycadu/) pour expérimenter cela avec un code complet, ou [cette version](https://jsfiddle.net/chrisvfritz/b2qj69o1/) pour un exemple lié à un objet d'option de composant plutôt qu'à un nom enregistré.
-``` js
-name: 'stack-overflow',
-template: '
'
-```
+C'est tout ce que vous avez besoin de savoir à propos des slot pour le moment, mais une fois que vous aurez fini de lire cette page et que vous vous sentirez à l'aise avec son contenu, nous vous recommandons de revenir pour lire le guide complet à propos des [Composants dynamiques et asynchrones](components-dynamic-async.html).
-Un composant comme celui ci-dessus conduira à une erreur « taille maximale de pile dépassée » ("max stack size exceeded"), donc assurez-vous que les invocations récursives soient conditionnelles (c.-à-d. utilisent un `v-if` qui vaudra éventuellement `false`).
+## Cas particuliers de l'analyse des templates de DOM
-### Références circulaires entre les composants
+Plusieurs éléments HTML, comme ``, ``, `` et `` ont des restrictions en ce qui concerne les éléments à l'intérieur desquels ils apparaissent. D'autres éléments quant à eux, tel que ``, ``, ou `` peuvent uniquement être placés à l'intérieur de certains éléments parents uniquement.
-Imaginons que vous construisiez une arborescence de fichiers, comme Finder ou File Explorer. Vous pouvez avoir un composant `tree-folder` avec ce template :
+Cela mène à des problèmes quand vous utilisez des composants avec des éléments qui ont ces restrictions. Par exemple :
``` html
@@ -1372,7 +576,7 @@ Imaginons que vous construisiez une arborescence de fichiers, comme Finder ou Fi
```
-Puis un composant `tree-folder-contents` avec ce template :
+Le composant personnalisé `` sera considéré comme un contenu invalide, causant des erreurs dans les rendus éventuels en sortie. Heureusement, l'attribut spécial `is` offre un moyen de contournement :
``` html
@@ -1380,70 +584,12 @@ Puis un composant `tree-folder-contents` avec ce template :
```
-En regardant attentivement, vous verrez que ces composants seront en fait l'ancêtre _et_ le descendant l'un de l'autre dans l'arbre de rendu — un paradoxe ! Quand vous inscrivez un composant de manière globale avec `Vue.component`, ce paradoxe est résolu pour vous automatiquement. Si c'est votre cas, vous pouvez arrêter de lire ici.
-
-Cependant, si vous réclamez/importez des composants en utilisant un __système de module__, c.-à-d. via webpack ou Browserify, vous obtiendrez une erreur « Échec de montage du composant : un template ou une fonction de rendu n'est pas défini. » :
-
-```
-Failed to mount component: template or render function not defined
-```
-
-Pour expliquer ce qui arrive, je vais appeler nos composants A et B. Le système de module voit de quoi A a besoin, d'abord A a besoin de B, mais B a besoin de A, mais A a besoin de B, etc., etc. Ça tourne en boucle, ne sachant pas comment complètement résoudre l'un ou l'autre des composants sans en résoudre un avant l'autre. Pour régler ça, nous avons besoin de donner au système de module un moyen de dire, « A a _éventuellement_ besoin de B, mais il n'y a pas de raison de résoudre B en premier. ».
-
-Dans notre cas, je ferais cela avec le composant `tree-folder`. Nous savons que l'enfant crée un paradoxe dans le composant `tree-folder-contents`, nous allons donc attendre le hook `beforeCreate` du cycle de vie pour l'inscrire :
-
-``` js
-beforeCreate: function () {
- this.$options.components.TreeFolderContents = require('./tree-folder-contents.vue').default
-}
-```
-
-Problème résolu !
-
-### Templates avec `inline-template`
-
-Quand l'attribut spécifique `inline-template` est présent sur le composant enfant, il va utiliser son contenu interne en tant que template, plutôt que de le traiter comme un contenu distribué. Cela permet une création de template plus flexible.
-
-``` html
-
-
-
Ceci est traité comme le template du composant lui-même.
-
Il n'y aura pas de transclusion de contenu.
-
-
-```
+Il doit être noté que **cette limitation _n'_affecte _pas_ les templates sous forme de chaine de caractères provenant d'une des sources suivantes** :
-Cependant, la propriété `inline-template` rend la portée de votre template difficile à appréhender. Pour une bonne pratique, optez plutôt pour définir vos templates à l'intérieur du composant en utilisant l'option `template` ou un élément `template` dans un fichier `.vue`.
+- Un template de chaine de caractères (par ex. `template: '...'`),
+- [Les composants monofichier (`.vue`)](single-file-components.html)
+- [`
-```
-
-``` js
-Vue.component('hello-world', {
- template: '#hello-world-template'
-})
-```
-
-Cela peut être pratique pour des démos avec de gros templates ou dans des applications extrêmement petites, mais cela devrait être évité dans tous les autres cas, car cela sépare les templates du reste de la définition du composant.
-
-### Composants statiques peu couteux avec `v-once`
-
-Faire le rendu d'éléments HTML est vraiment rapide avec Vue, mais parfois vous pouvez avoir un composant qui contient **beaucoup** de contenu statique. Dans ces cas, vous pouvez vous assurer qu'il n'est évalué qu'une seule fois puis mis en cache avec la directive `v-once` sur l'élément racine, comme cela :
-
-``` js
-Vue.component('terms-of-service', {
- template: `
-
-
Conditions d'utilisation
- ... beaucoup de contenu statique ...
-
- `
-})
-```
+Une fois que vous vous sentirez à l'aise avec les connaissances que vous venez fraichement d’acquérir, nous vous recommandons de revenir pour lire le guide complet à propos des [Composants dynamiques et asynchrones](components-dynamic-async.html) ainsi que les autres pages dans la partie Au cœur des composants de la barre de navigation latérale.