From c52dc18daf43200d00702bf2283a4fb38c80fa50 Mon Sep 17 00:00:00 2001 From: Bruno Lesieur Date: Thu, 29 Jun 2017 12:27:50 +0200 Subject: [PATCH 01/21] Review FR with officials terms Signed-off-by: Bruno Lesieur --- docs/fr/SUMMARY.md | 18 ++-- docs/fr/actions.md | 46 +++++---- docs/fr/api.md | 120 +++++++++++++--------- docs/fr/book.json | 20 +++- docs/fr/forms.md | 14 +-- docs/fr/getters.md | 42 +++++--- docs/fr/getting-started.md | 22 ++-- docs/fr/hot-reload.md | 14 +-- docs/fr/images/flow.png | Bin 69033 -> 10947 bytes docs/fr/images/vuex.png | Bin 21959 -> 40247 bytes docs/fr/intro.md | 44 ++++---- docs/fr/modules.md | 205 ++++++++++++++++++++++++++++++------- docs/fr/mutations.md | 63 ++++++------ docs/fr/plugins.md | 42 ++++---- docs/fr/state.md | 42 ++++---- docs/fr/strict.md | 10 +- docs/fr/structure.md | 22 ++-- docs/fr/testing.md | 56 +++++----- 18 files changed, 483 insertions(+), 297 deletions(-) diff --git a/docs/fr/SUMMARY.md b/docs/fr/SUMMARY.md index 109dac85c..bfc445d35 100644 --- a/docs/fr/SUMMARY.md +++ b/docs/fr/SUMMARY.md @@ -5,20 +5,20 @@ - [Vous cherchez la documentation de la v1.0 ?](https://github.com/vuejs/vuex/tree/1.0/docs) -- [Release Notes](https://github.com/vuejs/vuex/releases) +- [Notes de version](https://github.com/vuejs/vuex/releases) - [Installation](installation.md) -- [Qu'est-ce que Vuex ?](intro.md) -- [Débuter](getting-started.md) +- [Vuex, qu'est-ce que c'est ?](intro.md) +- [Pour commencer](getting-started.md) - Concepts de base - - [State](state.md) - - [Getters](getters.md) + - [État](state.md) + - [Accesseurs](getters.md) - [Mutations](mutations.md) - [Actions](actions.md) - [Modules](modules.md) - [Structure d'une application](structure.md) - [Plugins](plugins.md) -- [Strict Mode](strict.md) -- [Formulaires](forms.md) +- [Mode strict](strict.md) +- [Gestion des formulaires](forms.md) - [Tests](testing.md) -- [Hot Reloading](hot-reload.md) -- [Documentation API](api.md) +- [Rechargement à chaud](hot-reload.md) +- [Documentation de l'API](api.md) diff --git a/docs/fr/actions.md b/docs/fr/actions.md index 1fdaefa28..8eb68d444 100644 --- a/docs/fr/actions.md +++ b/docs/fr/actions.md @@ -2,7 +2,7 @@ Les actions sont similaires aux mutations, à la différence que : -- Au lieu de modifier le state, les actions committent des mutations. +- Au lieu de modifier l'état, les actions actent des mutations. - Les actions peuvent contenir des opérations asynchrones. Enregistrons une simple action : @@ -25,9 +25,9 @@ const store = new Vuex.Store({ }) ``` -Les handlers d'action reçoivent un objet contexte qui expose le même set de méthodes/propriétés que l'instance du store, donc vous pouvez appeler `context.commit` pour commiter une mutation, ou accéder au state et aux getters via `context.state` et `context.getters`. Nous verrons pourquoi cet objet contexte n'est pas l'instance du store elle-même lorsque nous présenterons les [Modules](moduels.md) plus tard. +Les gestionnaires d'action reçoivent un objet contexte qui expose le même ensemble de méthodes et propriétés que l'instance du store, donc vous pouvez appeler `context.commit` pour acter une mutation, ou accéder à l'état et aux accesseurs via `context.state` et `context.getters`. Nous verrons pourquoi cet objet contexte n'est pas l'instance du store elle-même lorsque nous présenterons les [Modules](modules.md) plus tard. -En pratique, nous utilisons souvent la [destructuration d'argument](https://github.com/lukehoban/es6features#destructuring) (*argument destructuring*) pour simplifier quelque peu le code (particulièrement si nous avons besoin d'appeler `commit` plusieurs fois) : +En pratique, nous utilisons souvent la [destructuration d'argument](https://developer.mozilla.org/fr/docs/Web/JavaScript/Reference/Op%C3%A9rateurs/Affecter_par_d%C3%A9composition) pour simplifier quelque peu le code (particulièrement si nous avons besoin d'appeler `commit` plusieurs fois) : ``` js actions: { @@ -37,7 +37,7 @@ actions: { } ``` -### Dispatcher des actions dans les composants +### Propager des actions dans les composants Les actions sont déclenchées par la méthode `store.dispatch` : @@ -57,47 +57,48 @@ actions: { } ``` -Les actions prennent en charge le même format de payload et *object-style dispatch* : +Les actions prennent également en charge les paramètres additionnels (« payload ») et les objets pour propager : ``` js -// dispatcher avec un payload +// propager avec un paramètre additionnel store.dispatch('incrementAsync', { amount: 10 }) -// dispatcher avec un object +// propager avec un objet store.dispatch({ type: 'incrementAsync', amount: 10 }) ``` -Un exemple plus pratique d'une application du monde réel serait une action pour check-out un panier d'achats, ce qui implique **d'appeler une API asynchrone** et de **comitter de multiples mutations** : +Un exemple concret d'application serait une action pour vider un panier d'achats, ce qui implique **d'appeler une API asynchrone** et d'**acter de multiples mutations** : ``` js actions: { checkout ({ commit, state }, products) { // sauvegarder les articles actuellement dans le panier const savedCartItems = [...state.cart.added] - // envoyer la requête de checkout, et vider le panier + // envoyer la requête de checkout, + // et vider le panier commit(types.CHECKOUT_REQUEST) - // l'API du shop prend un callback success et un callback failure + // l'API de la boutique en ligne prend une fonction de rappel en cas de succès et une autre en cas d'échec shop.buyProducts( products, - // handle success + // gérer le succès () => commit(types.CHECKOUT_SUCCESS), - // handle failure + // gérer l'échec () => commit(types.CHECKOUT_FAILURE, savedCartItems) ) } } ``` -Notez que nous procédons à un flux d'opérations asynchrones, et enregistrons les effets de bord (mutation du state) de l'action en les committant. +Notez que nous procédons à un flux d'opérations asynchrones, et enregistrons les effets de bord (mutation de l'état) de l'action en les actant. -### Dispatcher des actions dans les composants +### Propager des actions dans les composants -Vous pouvez dispatcher des actions dans les composants avec `this.$store.dispatch('xxx')`, ou en utilisant le helper `mapActions` qui attache les méthodes du composant aux appels de `store.dispatch` (nécessite l'injection de `store` à la racine) : +Vous pouvez propager des actions dans les composants avec `this.$store.dispatch('xxx')`, ou en utilisant la fonction utilitaire `mapActions` qui attache les méthodes du composant aux appels de `store.dispatch` (nécessite l'injection de `store` à la racine) : ``` js import { mapActions } from 'vuex' @@ -106,10 +107,13 @@ export default { // ... methods: { ...mapActions([ - 'increment' // attacher this.increment() à this.$store.dispatch('increment') + 'increment' // attacher `this.increment()` à `this.$store.dispatch('increment')` + + // `mapActions` supporte également les paramètres additionnels : + 'incrementBy' // attacher `this.incrementBy(amount)` à `this.$store.dispatch('incrementBy', amount)` ]), ...mapActions({ - add: 'increment' // attacher this.add() à this.$store.dispatch('increment') + add: 'increment' // attacher `this.add()` à `this.$store.dispatch('increment')` }) } } @@ -119,7 +123,7 @@ export default { Les actions sont souvent asynchrones, donc comment savoir lorsqu'une action est terminée ? Et plus important, comment composer plusieurs actions ensemble pour manipuler des flux asynchrones plus complexes ? -La première chose à savoir est que `store.dispatch` retourne la valeur retournée par le handler de l'action déclenchée, vous pouvez donc retourner une Promise : +La première chose à savoir est que `store.dispatch` peut gérer la Promesse (« Promise ») retournée par le gestionnaire d'action déclenché et par conséquent vous pouvez également retourner une Promesse : ``` js actions: { @@ -158,17 +162,17 @@ actions: { Pour finir, nous pouvons utiliser de [async / await](https://tc39.github.io/ecmascript-asyncawait/), une fonctionnalité JavaScript qui sera disponible très bientôt, nous pouvons composer nos actions ainsi : ``` js -// sachant que getData() et getOtherData() retournent des Promises +// sachant que `getData()` et `getOtherData()` retournent des Promesses. actions: { async actionA ({ commit }) { commit('gotData', await getData()) }, async actionB ({ dispatch, commit }) { - await dispatch('actionA') // wait for actionA to finish + await dispatch('actionA') // attendre que `actionA` soit finie commit('gotOtherData', await getOtherData()) } } ``` -> Il est possible pour un `store.dispatch` de déclencher plusieurs handlers d'action dans différents modules. Dans ce genre de cas, la valeur retournée sera une Promise qui se résoud quand tous les handlers déclenchés ont été résolus. +> Il est possible pour un `store.dispatch` de déclencher plusieurs gestionnaires d'action dans différents modules. Dans ce genre de cas, la valeur retournée sera une Promesse qui se résoud quand tous les gestionnaires déclenchés ont été résolus. diff --git a/docs/fr/api.md b/docs/fr/api.md index b39121375..eb0b2034c 100644 --- a/docs/fr/api.md +++ b/docs/fr/api.md @@ -1,6 +1,6 @@ -# Documentation API +# Documentation de l'API -### Vuex.Store +### `Vuex.Store` ``` js import Vuex from 'vuex' @@ -8,37 +8,37 @@ import Vuex from 'vuex' const store = new Vuex.Store({ ...options }) ``` -### Options de constructeur de Vuex.Store +### Options du constructeur de `Vuex.Store` - **state** - - type: `Object` + - type : `Object` - L'objet state racine pour le store Vuex. + L'objet d'état racine pour le store Vuex. [Détails](state.md) - **mutations** - - type: `{ [type: string]: Function }` + - type : `{ [type: string]: Function }` - Enregistrer les mutations sur le store. La fonction handler reçoit toujours `state` comme premier argument (sera le state local du module si défini dans un module), et reçoit le `payload` en second argument s'il y en a un. + Enregistrer les mutations sur le store. La fonction gestionnaire reçoit toujours `state` comme premier argument (sera l'état local du module si défini dans un module), et reçoit le `payload` en second argument s'il y en a un. [Détails](mutations.md) - **actions** - - type: `{ [type: string]: Function }` + - type : `{ [type: string]: Function }` - Enregistrer les actions sur le store. La fonction handler reçoit un objet `context` qui expose les propriétés suivantes : + Enregistrer les actions sur le store. La fonction gestionnaire reçoit un objet `context` qui expose les propriétés suivantes : ``` js { - state, // identique à store.state, ou au state local si dans des modules - rootState, // identique à store.state, seulement dans des modules - commit, // identique à store.commit - dispatch, // identique à store.dispatch - getters // identique à store.getters + state, // identique à `store.state`, ou à l'état local si dans des modules + rootState, // identique à `store.state`, seulement dans des modules + commit, // identique à `store.commit` + dispatch, // identique à `store.dispatch` + getters // identique à `store.getters` } ``` @@ -46,30 +46,40 @@ const store = new Vuex.Store({ ...options }) - **getters** - - type: `{ [key: string]: Function }` + - type : `{ [key: string]: Function }` - Enregistrer les getters sur le store. La fonction getter reçoit les arguments suivants : + Enregistrer les accesseurs sur le store. La fonction accesseur reçoit les arguments suivants : ``` - state, // sera le state local du module si défini dans un module. - getters, // indentique à store.getters - rootState // indentique à store.state + state, // sera l'état local du module si défini dans un module. + getters // indentique à `store.getters` ``` - Les getters enregistrés sont exposés sur `store.getters`. + + Arguments spécifiques quand défini dans un module + + ``` + state, // sera l'état local du module si défini dans un module. + getters, // module local getters of the current module + rootState, // état global + rootGetters // tous les accesseurs + ``` + + Les accesseurs enregistrés sont exposés sur `store.getters`. [Détails](getters.md) - **modules** - - type: `Object` + - type : `Object` - Un objet contenant des sous-modules qui seront regroupés dans le store, de la forme suivante : + Un objet contenant des sous-modules qui seront regroupés dans le store, sous la forme suivante : ``` js { key: { state, - mutations, + namespaced?, + mutations?, actions?, getters?, modules? @@ -78,64 +88,64 @@ const store = new Vuex.Store({ ...options }) } ``` - Chaque module peut contenir `state` et `mutations`, tout comme les options racine. Le state d'un module sera attaché au state racine du store en utilisant la clé du module. Les mutations et getters d'un module recevront seulement le state local du module en premier argument au lieu du state racine, et le `context.state` des actions du module pointeront également vers le state local. + Chaque module peut contenir `state` et `mutations`, tout comme les options racine. L'état d'un module sera attaché à l'état racine du store en utilisant la clé du module. Les mutations et accesseurs d'un module recevront seulement l'état local du module en premier argument au lieu de l'état racine, et le `context.state` des actions du module pointeront également vers l'état local. [Détails](modules.md) - **plugins** - - type: `Array` + - type : `Array` - Un tableau de fonctions plugin qui seront appliqués au store. Un plugin reçoit simplement le store comme seul argument et peut soit écouter les mutations (pour la persistence de données, logging ou debugging) ou dispatcher des mutations (pour les données internes, i.e. websockets ou observables). + Un tableau de fonctions plugins qui seront appliquées au store. Un plugin reçoit simplement le store comme seul argument et peut soit écouter les mutations (pour la persistence de données, les logs ou le débogage) ou propager des mutations (pour les données internes, c.-à-d. websockets ou observables). [Détails](plugins.md) - **strict** - - type: `Boolean` + - type : `Boolean` - default: `false` - Force le store Vuex en mode strict. En mode strict, toute mutation du state en dehors des handlers de mutation lancera une Error. + Force le store Vuex en mode strict. En mode strict, toute mutation de l'état en dehors des gestionnaires de mutation lancera une erreur. [Détails](strict.md) -### Propriétés d'instance de Vuex.Store +### Propriétés d'instance de `Vuex.Store` - **state** - - type: `Object` + - type : `Object` - Le state racine. Lecture seule. + L'état racine. Lecture seule. - **getters** - - type: `Object` + - type : `Object` - Expose les getters enregistrés. Lecture seule. + Expose les accesseurs enregistrés. Lecture seule. -### Méthodes d'instance de Vuex.Store +### Méthodes d'instance de `Vuex.Store` -- **`commit(type: string, payload?: any) | commit(mutation: Object)`** +- **`commit(type: string, payload?: any, options?: Object) | commit(mutation: Object, options?: Object)`** - commiter une mutation. [Détails](mutations.md) + Acter une mutation. `options` peut avoir `root: true` ce qui permet d'acter des mutations racines dans des [modules sous espace de nom](modules.md#namespacing). [Détails](mutations.md) -- **`dispatch(type: string, payload?: any) | dispatch(action: Object)`** +- **`dispatch(type : string, payload?: any, options?: Object) | dispatch(action: Object, options?: Object)`** - Dispatcher une action. Retourne la valeur renvoyée par le handler d'action déclenché, ou une Promise si plusieurs handlers ont été déclenchés. [Détails](actions.md) + Propager une action. Retourne la valeur renvoyée par le gestionnaire d'action déclenché, ou une Promesse si plusieurs gestionnaires ont été déclenchés. [Détails](actions.md) - **`replaceState(state: Object)`** - Remplacer le state racine du store. Utiliser seulement pour hydrater le state ou voir le state dans le temps. + Remplacer l'état racine du store. Utiliser seulement pour hydrater l'état ou dans le but de voyager dans le temps. - **`watch(getter: Function, cb: Function, options?: Object)`** - Observer de façon réactive la valeur de retour d'une fonction getter, et appeler le callback lorsque la valeur change. Le getter reçoit le state du store comme unique argument. Accepte un objet options optionnel qui prend les mêmes options que la méthode `vm.$watch` de Vue. + Observer de façon réactive la valeur de retour d'une fonction accesseur, et appeler la fonction de rappel lorsque la valeur change. L'accesseur reçoit l'état du store comme unique argument. Accepte un objet optionnel d'options qui prend les mêmes options que la méthode `vm.$watch` de Vue. - Pour arrêter d'observer, appeler la fonction retournée. + Pour arrêter d'observer, appeler la fonction gestionnaire retournée. - **`subscribe(handler: Function)`** - S'abonner aux mutations du store. Le `handler` est appelé après chaque mutation et reçoit le descripteur de mutation et le state post-mutation comme arguments : + S'abonner aux mutations du store. Le `handler` est appelé après chaque mutation et reçoit le descripteur de mutation et l'état post-mutation comme arguments : ``` js store.subscribe((mutation, state) => { @@ -158,20 +168,28 @@ const store = new Vuex.Store({ ...options }) Remplacement à la volée des nouvelles actions et mutations. [Détails](hot-reload.md) -### Helpers d'attachement au composant +### Fonctions utilitaires d'attachement au composant + +- **`mapState(namespace?: string, map: Array | Object): Object`** + + Créer des propriétés calculées qui retournent le sous arbre du store Vuex au composant. [Détails](state.md#le-helper-mapstate) + + Le premier argument peut être de façon optionnel une chaîne d'espace de nom. [Details](modules.md#Fonctions-utilitaires-liées-avec-espace-de-nom) + +- **`mapGetters(namespace?: string, map: Array | Object): Object`** -- **`mapState(map: Array | Object): Object`** + Créer des propriétés calculées qui retournent la valeur calculée d'un accesseur. [Détails](getters.md#la-function-utilitaire-mapgetters) - Créer des computed properties qui retournent le sub tree du store Vuex au composant. [Détails](state.md#le-helper-mapstate) + Le premier argument peut être de façon optionnel une chaîne d'espace de nom. [Details](modules.md#Fonctions-utilitaires-liées-avec-espace-de-nom) -- **`mapGetters(map: Array | Object): Object`** +- **`mapActions(namespace?: string, map: Array | Object): Object`** - Créer des computed properties qui retournent la valeur calculée d'un getter. [Détails](getters.md#le-helper-mapgetters) + Créer des méthodes de composant qui propagent une action. [Détails](actions.md#propager-des-actions-dans-les-composants) -- **`mapActions(map: Array | Object): Object`** + Le premier argument peut être de façon optionnel une chaîne d'espace de nom. [Details](modules.md#Fonctions-utilitaires-liées-avec-espace-de-nom) - Créer des méthodes de composant qui dispatchent une action. [Détails](actions.md#dispatcher-des-actions-dans-les-composants) +- **`mapMutations(namespace?: string, map: Array | Object): Object`** -- **`mapMutations(map: Array | Object): Object`** + Créer des méthodes de composant qui actent une mutation. [Détails](mutations.md#acter-des-mutations-dans-les-composants) - Créer des méthodes de composant qui committent une mutation. [Détails](mutations.md#commiter-des-mutations-dans-les-composants) + Le premier argument peut être de façon optionnel une chaîne d'espace de nom. [Details](modules.md#Fonctions-utilitaires-liées-avec-espace-de-nom) diff --git a/docs/fr/book.json b/docs/fr/book.json index bfb9e5a3d..428c98162 120000 --- a/docs/fr/book.json +++ b/docs/fr/book.json @@ -1 +1,19 @@ -../book.json \ No newline at end of file +{ + "gitbook": "2.x.x", + "plugins": ["edit-link", "prism", "-highlight", "github"], + "pluginsConfig": { + "edit-link": { + "base": "https://github.com/vuejs/vuex/tree/dev/docs", + "label": "Éditer cette page" + }, + "github": { + "url": "https://github.com/vuejs/vuex/" + } + }, + "links": { + "sharing": { + "facebook": false, + "twitter": false + } + } +} diff --git a/docs/fr/forms.md b/docs/fr/forms.md index 94da84383..f304def1c 100644 --- a/docs/fr/forms.md +++ b/docs/fr/forms.md @@ -1,14 +1,14 @@ -# Formulaires +# Gestion des formulaires -Lorsque l'on utilise Vuex en mode strict, il peut être compliqué d'utiliser `v-model` sur une partie du state qui appartient à Vuex : +Lorsque l'on utilise Vuex en mode strict, il peut être compliqué d'utiliser `v-model` sur une partie de l'état qui appartient à Vuex : ``` html ``` -Supposons que `obj` est une computed property qui retourne un Object depuis le store, le `v-model` tentera de muter directement `obj.message` lorsque l'utilisateur saisit du texte dans le champ. En mode strict, cela produira une erreur car la mutation n'est pas effectuée dans un handler de mutation Vuex explicite. +Supposons que `obj` est une propriété calculée qui retourne un objet depuis le store, le `v-model` tentera de muter directement `obj.message` lorsque l'utilisateur saisit du texte dans le champ. En mode strict, cela produira une erreur car la mutation n'est pas effectuée dans un gestionnaire de mutation Vuex explicite. -La "façon Vuex" de gérer ça est de binder la valeur de l'`input` est d'appeler une action sur l'event `input` ou `change` : +La « méthode Vuex » pour gérer ça est de lier la valeur de l'`input` et d'appeler une action sur l'évènement `input` ou `change` : ``` html @@ -27,7 +27,7 @@ methods: { } ``` -Et voici le handler de mutation : +Et voici le gestionnaire de mutation : ``` js // ... @@ -38,9 +38,9 @@ mutations: { } ``` -### Computed property bi-directionnelle +### Propriété calculée bidirectionnelle -Admettons tout de même que l'exemple ci-dessus est plus verbeux que le `v-model` couplé au state local, et on perd quelques fonctionnalités pratiques de `v-model` au passage. Une approche alternative consiste à utiliser une computed property bi-directionnelle avec un setter : +Admettons tout de même que l'exemple ci-dessus est plus verbeux que le `v-model` couplé à l'état local (tout en perdant quelques fonctionnalités pratiques de `v-model` au passage). Une approche alternative consiste à utiliser une propriété calculée bidirectionnelle avec un mutateur : ``` html diff --git a/docs/fr/getters.md b/docs/fr/getters.md index 046b3f703..826bac3dc 100644 --- a/docs/fr/getters.md +++ b/docs/fr/getters.md @@ -1,7 +1,6 @@ +# Accesseurs -# Getters - -Parfois nous avons besoin de calculer des valeurs basées sur le state du store, par exemple pour filtrer une liste d'éléments et les compter : +Parfois nous avons besoin de calculer des valeurs basées sur l'état du store, par exemple pour filtrer une liste d'éléments et les compter : ``` js computed: { @@ -11,9 +10,11 @@ computed: { } ``` -Si plus d'un composant a besoin d'utiliser cela, il nous faut ou bien dupliquer cette fonction, ou bien l'extraire dans un helper séparé et l'importer aux endroits nécessaires — les deux idées sont loin d'être idéales. +Si plus d'un composant a besoin d'utiliser cela, il nous faut ou bien dupliquer cette fonction, ou bien l'extraire dans une fonction utilitaire séparée et l'importer aux endroits nécessaires. Les deux idées sont loin d'être idéales. + +Vuex nous permet de définir des accesseurs (« getters ») dans le store. Voyez-les comme les propriétés calculées des stores. Comme pour les propriétés calculées, le résultat de l'accesseur est mis en cache en se basant sur ses dépendances et il ne sera ré-évalué quand l'une de ses dépendances aura changé. -Vuex nous permet de définir des "getters" dans le store (voyez-les comme les computed properties des store). Les getters prennent le state en premier argument : +Les accesseurs prennent l'état en premier argument : ``` js const store = new Vuex.Store({ @@ -31,13 +32,13 @@ const store = new Vuex.Store({ }) ``` -Les getters seront exposé sur l'objet `store.getters` : +Les accesseurs seront exposés sur l'objet `store.getters` : ``` js store.getters.doneTodos // -> [{ id: 1, text: '...', done: true }] ``` -Les getters recevront également les autres getters en second argument : +Les accesseurs recevront également les autres accesseurs en second argument : ``` js getters: { @@ -62,9 +63,24 @@ computed: { } ``` -### Le helper `mapGetters` +Vous pouvez aussi passer des arguments aux accesseurs en retournant une fonction. Cela est particulièrement utile quand vous souhaitez interroger un tableau dans le store : + +```js +getters: { + // ... + getTodoById: (state, getters) => (id) => { + return state.todos.find(todo => todo.id === id) + } +} +``` + +``` js +store.getters.getTodoById(2) // -> { id: 2, text: '...', done: false } +``` + +### La fonction utilitaire `mapGetters` -Le helper `mapGetters` attache simplement vos getters du store aux computed properties locales : +La fonction utilitaire `mapGetters` attache simplement vos accesseurs du store aux propriétés calculées locales : ``` js import { mapGetters } from 'vuex' @@ -72,7 +88,7 @@ import { mapGetters } from 'vuex' export default { // ... computed: { - // rajouter les getters dans computed avec l'object spread operator + // rajouter les accesseurs dans `computed` avec l'opérateur de décomposition ...mapGetters([ 'doneTodosCount', 'anotherGetter', @@ -82,11 +98,11 @@ export default { } ``` -Si vous voulez attacher un getter avec un nom différent, utilisez un objet : +Si vous voulez attacher un accesseur avec un nom différent, utilisez un objet : ``` js -mapGetters({ - // attacher this.doneCount à store.getters.doneTodosCount +...mapGetters({ + // attacher `this.doneCount` à `store.getters.doneTodosCount` doneCount: 'doneTodosCount' }) ``` diff --git a/docs/fr/getting-started.md b/docs/fr/getting-started.md index 2104862ea..63437ecd2 100644 --- a/docs/fr/getting-started.md +++ b/docs/fr/getting-started.md @@ -1,19 +1,19 @@ -# Débuter +# Pour commencer -Au cœur de chaque application Vuex, il y a le **store**. Un "store" est tout simplement un conteneur avec le **state** de votre application. Il y a deux choses qui différencient un store Vuex d'un simple objet global : +Au cœur de chaque application Vuex, il y a la **zone de stockage (« store »)**. Un « store » est tout simplement un conteneur avec l'**état (« state »)** de votre application. Il y a deux choses qui différencient un store Vuex d'un simple objet global : -1. Les stores Vuex sont réactifs. Quand les composants Vue y récupèrent le state, ils modifieront efficacement et de façon réactive si le state du store change. +1. Les stores Vuex sont réactifs. Quand les composants Vue y récupèrent l'état, ils se mettront à jour de façon réactive et efficace si l'état du store a changé. -2. Vous ne pouvez pas muter directement le state du store. La seule façon de modifier le state d'un store est de **commiter** explicitement des **mutations**. Cela assure que chaque état laisse un enregistrement traçable, et permette à des outils de mieux nous aider à comprendre nos applications. +2. Vous ne pouvez pas muter directement l'état du store. La seule façon de modifier l'état d'un store est d'**acter (« commit »)** explicitement des **mutations**. Cela assure que chaque état laisse un enregistrement traçable, et permet à des outils de nous aider à mieux appréhender nos applications. ### Le store le plus simple > **NOTE:** Nous allons utiliser la syntaxe ES2015 dans les exemples de code pour le reste de la documentation. Si vous ne vous êtes pas encore penché dessus, [vous devriez](https://babeljs.io/docs/learn-es2015/) ! -Après [avoir installé](installation.md) Vuex, nous allons créer un store. C'est assez simple — définissez juste un objet state initial et quelques mutations : +Après [avoir installé](installation.md) Vuex, nous allons créer un store. C'est assez simple ; définissez juste un objet d'état initial et quelques mutations : ``` js -// Make sure to call Vue.use(Vuex) first if using a module system +// Assurez vous d'appeler `Vuex.use(Vuex)` en premier lieu si vous utilisez un système de module const store = new Vuex.Store({ state: { @@ -27,7 +27,7 @@ const store = new Vuex.Store({ }) ``` -Maintenant, vous pouvez accéder à l'objet state avec `store.state`, et déclencher un changement de state avec la méthode `store.commit` : +Maintenant, vous pouvez accéder à l'objet d'état avec `store.state`, et déclencher un changement d'état avec la méthode `store.commit` : ``` js store.commit('increment') @@ -35,10 +35,10 @@ store.commit('increment') console.log(store.state.count) // -> 1 ``` -Encore une fois, la raison pour laquelle nous committons une mutation au lieu de modifier `store.state.count` directement, c'est parce que nous voulons le tracer explicitement. Cette simple convention rend votre intention plus explicite, ainsi vous pouvez raisonner plus facilement les changements de state en lisant votre code. De plus, cela nous donne l'opportunité d'implémenter des outils qui peuvent enregistrer chaque mutation, prendre des instantanés du state, ou même procéder à du debugging dans le temps. +Encore une fois, la raison pour laquelle nous actons une mutation au lieu de modifier `store.state.count` directement, c'est parce que nous voulons le tracer explicitement. Cette simple convention rend votre intention plus explicite, ainsi vous pouvez raisonner plus facilement les les changements d'état en lisant votre code. De plus, cela nous donne l'opportunité d'implémenter des outils qui peuvent enregistrer chaque mutation, prendre des instantanés de l'état, ou même procéder à de la visualisation d'état dans le temps. -Utiliser le state du store dans un composant implique simplement de retourner le state dans une *computed property*, car le state du store est réactif. Déclencher des changements signifie simplement commiter des mutations dans les méthodes du composant. +Utiliser l'état du store dans un composant implique simplement de retourner l'état dans une *propriété calculée*, car l'état du store est réactif. Déclencher des changements signifie simplement d'acter des mutations dans les méthodes du composant. -Voici un exemple de la [plus basique app Vuex de compteur](https://jsfiddle.net/n9jmu5v7/1269/). +Voici un exemple de l'[application de comptage Vuex la plus basique](https://jsfiddle.net/n9jmu5v7/1269/). -Ensuite, nous allons examiner chaque concept de base plus en détails, et commençons avec le [State](state.md). +Ensuite, nous allons examiner chaque concept de base plus en détails, et commençons avec l'[État](state.md). diff --git a/docs/fr/hot-reload.md b/docs/fr/hot-reload.md index 93c36e2ca..53adcd7f4 100644 --- a/docs/fr/hot-reload.md +++ b/docs/fr/hot-reload.md @@ -1,6 +1,6 @@ -# Hot Reloading +# Rechargement à chaud -Vuex prend en charge le `hot-reloading` des mutations, modules, actions et getters durant le développement, en utilisant l'[API Hot Module Replacement](https://webpack.github.io/docs/hot-module-replacement.html) de webpack. Vous pouvez également utiliser Browserify avec le plugin [browserify-hmr](https://github.com/AgentME/browserify-hmr/). +Vuex prend en charge le rechargement à chaud des mutations, modules, actions et accesseurs durant le développement, en utilisant l'[API du module de remplacement à chaud](https://webpack.github.io/docs/hot-module-replacement.html) de webpack. Vous pouvez également utiliser Browserify avec le plugin [browserify-hmr](https://github.com/AgentME/browserify-hmr/). Pour les mutations et les modules, vous aurez besoin d'utiliser la méthode d'API `store.hotUpdate()` : @@ -24,13 +24,13 @@ const store = new Vuex.Store({ }) if (module.hot) { - // accept actions and mutations as hot modules + // accepter les actions et mutations en tant que module à chaud module.hot.accept(['./mutations', './modules/a'], () => { - // require the updated modules - // have to add .default here due to babel 6 module output + // requiert les modules à jour + // ajout de `.default` ici pour les sorties des modules babel 6 const newMutations = require('./mutations').default const newModuleA = require('./modules/a').default - // swap in the new actions and mutations + // remplacer les nouvelles actions et mutations store.hotUpdate({ mutations: newMutations, modules: { @@ -41,4 +41,4 @@ if (module.hot) { } ``` -Jetez un œil à [l'exemple counter-hot](https://github.com/vuejs/vuex/tree/dev/examples/counter-hot) pour jouer avec le hot-reload. +Jetez un œil à [l'exemple counter-hot](https://github.com/vuejs/vuex/tree/dev/examples/counter-hot) pour jouer avec du rechargement à chaud. diff --git a/docs/fr/images/flow.png b/docs/fr/images/flow.png index fd9b97d5947829d9a4ba6d1869b6f4c91b48f767..acbaf4119cfcb0a8a7c27bcf7a80b05a9ffe2f6e 100644 GIT binary patch literal 10947 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 EUl}O2b^rhX diff --git a/docs/fr/images/vuex.png b/docs/fr/images/vuex.png index 0181299473acaed53c88ae6f38deb086eea824b7..82b9900d8040a9ef8c54b5baae11446a95f0d41c 100644 GIT binary patch literal 40247 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

VtuL~Kifl8QK8~W} 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 count }} `, @@ -27,39 +27,37 @@ new Vue({ }) ``` -C'est une app auto-contenue avec les parties suivantes : +C'est une application auto-suffisante avec les parties suivantes : -- L'**État** (_state_), qui est la source de vérité qui dirige notre app; -- La **Vue** (_view_), qui est juste un mapping déclaratif du **state**; -- Les **actions**, qui sont les façons possibles pour le state de changer en réaction aux actions de l'utilisateur depuis la **vue**. +- L'**état**, qui est la source de vérité qui pilotant votre application, +- La **vue**, qui est une réflexion déclarative de l'**état**, +- Les **actions**, qui sont les façons possibles pour l'état de changer en réaction aux actions utilisateurs depuis la **vue**. -Voici une représentation extrèmement simple du concept de "one-way data flow" (_flux de données unidirectionnel_) : +Voici une représentation extrèmement simple du concept de « flux de donnée unidirectionnel » :

-Cependant, la simplicité s'évapore rapidement lorsque nous avons **de multiples composants qui partagent le même state** : +Cependant, la simplicité s'évapore rapidement lorsque nous avons **de multiples composants qui partagent un même état global** : -- Plusieurs vues peuvent dépendre de la même partie du state. -- Des actions dans différentes vues peuvent avoir besoin de muter la même partie du state. +- Plusieurs vues peuvent dépendre de la même partie de l'état global. +- Des actions dans différentes vues peuvent avoir besoin de muter la même partie de l'état global. -Pour le premier problème, passer des propriétés peut être fastidieux pour les composants profondément imbriqués, et ça ne fonctionne tout simplement pas pour les composants d'un même parent. Pour le deuxième problème, on se retrouve souvent à se rabattre sur des solutions telles qu'accéder aux références d'instance du parent/enfant direct ou essayer de muter et synchroniser de multiples copies du state via des events. Ces deux patterns sont fragiles et posent rapidement des problèmes de maintenabilité du code. +Pour le premier problème, passer des props peut être fastidieux pour les composants profondément imbriqués, et ça ne fonctionne tout simplement pas pour les composants d'un même parent. Pour le deuxième problème, on se retrouve souvent à se rabattre sur des solutions telles qu'accéder aux références d'instance du parent/enfant direct ou essayer de muter et synchroniser de multiples copies de l'état via des évènements. Ces deux modèles sont fragiles et posent rapidement des problèmes de maintenabilité du code. -Alors pourquoi ne pas extraire le state partagé des composants, et le gérer dans un singleton global ? De cette manière, notre arbre de composant devient une grosse "view", et n'importe-quel composant peut accéder au state ou déclencher des actions, peu importe où il se trouve dans l'arbre ! +Alors pourquoi ne pas extraire l'état global partagé des composants, et le gérer dans un singleton global ? De cette manière, notre arbre de composant devient une grosse « vue », et n'importe quel composant peut accéder à l'état global ou déclencher des actions, peu importe où il se trouve dans l'arbre ! -De plus, en définissant et en séparant les concepts impliqués dans la gestion d'un state et en appliquant certaines règles, on donne aussi une structure et une maintenabilité à notre code. +De plus, en définissant et en séparant les concepts impliqués dans la gestion de l'état global et en appliquant certaines règles, on donne aussi une structure et une maintenabilité à notre code. -Voilà l'idée de base derrière Vuex, inspiré par [Flux](https://facebook.github.io/flux/docs/overview.html), [Redux](http://redux.js.org/) et [l'Architecture Elm](https://guide.elm-lang.org/architecture/). À l'inverse des autres patterns, Vuex est aussi une bibliothèque d'implémentation conçue spécialement pour Vue.js afin de bénéficier de son système de réactivité granulaire pour des modifications efficaces. +Voilà l'idée de base derrière Vuex, inspiré par [Flux](https://facebook.github.io/flux/docs/overview.html), [Redux](http://redux.js.org/) et [l'architecture Elm](https://guide.elm-lang.org/architecture/). À l'inverse des autres modèles, Vuex est aussi une bibliothèque d'implémentation conçue spécialement pour Vue.js afin de bénéficier de son système de réactivité granulaire pour des modifications efficaces. ![vuex](./images/vuex.png) ### Quand l'utiliser ? -Bien que Vuex nous aide à gérer une state partagé, il apporte aussi le coût de nouveaux concepts et _boilerplate_. C'est un compromis entre la productivité à court terme et à long terme. +Bien que Vuex nous aide à gérer un état global partagé, il apporte aussi le coût de nouveaux concepts et _abstraction de code_ (« boilerplate »). C'est un compromis entre la productivité à court terme et à long terme. -Si vous n'avez jamais créé une _Single Page Application_ à grande échelle et que vous sautez directement dans Vuex, cela peut paraître verbeux et intimidant. C'est parfaitement normal — si votre application est simple, vous vous en sortirez sans doute très bien sans Vuex. Un simple [bus d'event global](http://vuejs.org/guide/components.html#Non-Parent-Child-Communication) pourrait très bien vous suffire. Mais si vous devez créer une SPA à moyenne ou grande échelle, il y a des chances que vous vous trouviez dans des situations qui vous feront penser à une meilleure façon de gérer le state en-dehors de votre composant Vue, et Vuex sera naturellement la prochaine étape pour vous. Voici une bonne citation de Dan Abramov, l'auteur de Redux : +Si vous n'avez jamais créé une _application monopage_ à grande échelle et que vous sautez directement dans Vuex, cela peut paraître verbeux et intimidant. C'est parfaitement normal ; si votre application est simple, vous vous en sortirez sans doute très bien sans Vuex. Un simple [canal d'évènement global](https://fr.vuejs.org/v2/guide/components.html#Communication-non-parent-enfant) pourrait très bien vous suffire. Mais si vous devez créer une application monopage à moyenne ou grande échelle, il y a des chances que vous vous trouviez dans des situations qui vous feront vous interroger sur une meilleure gestion de l'état global, détaché de votre composant Vue, et Vuex sera naturellement la prochaine étape pour vous. Voici une bonne citation de Dan Abramov, l'auteur de Redux : -> Flux libraries are like glasses: you’ll know when you need them. -> -> _Les librairies Flux, c'est comme les lunettes : vous saurez quand vous en aurez besoin._ +> « Les librairies Flux, c'est comme les lunettes : vous saurez quand vous en aurez besoin. » diff --git a/docs/fr/modules.md b/docs/fr/modules.md index 780a9d13b..f6d2dea71 100644 --- a/docs/fr/modules.md +++ b/docs/fr/modules.md @@ -1,8 +1,8 @@ # Modules -Parce qu'il utilise un _single state tree_, tout le state de notre application est contenu dans un seul et même gros objet. Cependant, au fur et à mesure que notre application grandit, le store peut devenir très engorgé. +Du fait de l'utilisation d'un arbre d'état unique, tout l'état de notre application est contenu dans un seul et même gros objet. Cependant, au fur et à mesure que notre application grandit, le store peut devenir très engorgé. -Pour y remédier, Vuex nous permet de diviser notre store en **modules**. Chaque module peut contenir son propre state, mutations, actions, getters, et même d'autres modules. +Pour y remédier, Vuex nous permet de diviser notre store en **modules**. Chaque module peut contenir ses propres état, mutations, actions, accesseurs. Il peut même contenir ses propres modules internes. ``` js const moduleA = { @@ -25,20 +25,20 @@ const store = new Vuex.Store({ } }) -store.state.a // -> le state du module A -store.state.b // -> le state du module B +store.state.a // -> l'état du `moduleA` +store.state.b // -> l'état du `moduleB` ``` -### State local d'un module +### État local d'un module -Dans les mutations et getters d'un module, le premier argument reçu sera le **state local du module**. +Dans les mutations et accesseurs d'un module, le premier argument reçu sera **l'état local du module**. ``` js const moduleA = { state: { count: 0 }, mutations: { increment (state) { - // state est le state du module local + // `state` est l'état du module local state.count++ } }, @@ -51,7 +51,7 @@ const moduleA = { } ``` -De façon similaire, dans les actions du module, `context.state` exposera le state local, et le state racine sera disponible avec `context.rootState` : +De façon similaire, dans les actions du module, `context.state` exposera l'état local, et l'état racine sera disponible avec `context.rootState` : ``` js const moduleA = { @@ -66,7 +66,7 @@ const moduleA = { } ``` -Également, dans les getters du module, le state racine sera exposé en troisième argument : +Également, dans les accesseurs du module, l'état racine sera exposé en troisième argument : ``` js const moduleA = { @@ -79,60 +79,189 @@ const moduleA = { } ``` -### Namespacing +### Espace de nom -Notez que les actions, mutations et getters dans un module sont toujours enregistrés sous le **namespace global** — cela permet à plusieurs modules de réagir au même type de mutation/action. Vous pouvez répartir les modules dans des namespaces vous-mêmes afin d'éviter les conflits de nom en préfixant ou suffixant leurs noms. Et vous devriez probablement faire cela si vous utiliser un module Vuex réutilisable qui sera utilisé dans des environnements inconnus. Par exemple, nous voulons créer un module `todos` : +Par défaut, les actions, mutations et accesseurs à l'intérieur d'un module sont toujours enregistrés sous l'**espace de nom global**. Cela permet à de multiples modules d'être réactifs au même type de mutation et d'action. -``` js -// types.js +Si vous souhaitez que votre module soit auto-suffisant et réutilisable, vous pouvez le ranger sous un espace de nom avec `namespaced: true`. Quand le module est enregistré, tous ses accesseurs, actions et mutations seront automatiquement basés sur l'espace de nom du module dans lesquels ils sont rangés. Par exemple : + +```js +const store = new Vuex.Store({ + modules: { + account: { + namespaced: true, + + // propriétés du module + state: { ... }, // l'état du module est déjà imbriqué et n'est pas affecté par l'option `namespace` + getters: { + isAdmin () { ... } // -> getters['account/isAdmin'] + }, + actions: { + login () { ... } // -> dispatch('account/login') + }, + mutations: { + login () { ... } // -> commit('account/login') + }, + + // modules imbriqués + modules: { + // hérite de l'espace de nom du module parent + myPage: { + state: { ... }, + getters: { + profile () { ... } // -> getters['account/profile'] + } + }, + + // utilise un espace de nom imbriqué + posts: { + namespaced: true, -// on définit les noms des getters, actions et mutations en tant que constantes -// et on les préfixe du nom du module `todos` -export const DONE_COUNT = 'todos/DONE_COUNT' -export const FETCH_ALL = 'todos/FETCH_ALL' -export const TOGGLE_DONE = 'todos/TOGGLE_DONE' + state: { ... }, + getters: { + popular () { ... } // -> getters['account/posts/popular'] + } + } + } + } + } +}) ``` +Les accesseurs et actions sous espace de nom reçoivent des `getters`, `dispatch` et `commit` localisés. En d'autres termes, vous pouvez utiliser les paramètres de module sans écrire de prefix dans ce même module. Permuter entre un espace de nom ou non n'affecte pas le code à l'intérieur du module. + +#### Accéder aux propriétés globales dans les modules à espace de nom + +Si vous voulez utiliser des états et accesseurs globaux, `rootState` et `rootGetters` sont passés en 3ième et 4ième arguments des fonctions d'accès et sont également exposés en tant que propriété de l'objet `context` passé aux fonctions d'action. + +Pour propager les actions ou les mutations actées dans l'espace de nom global, passez `{ root: true }` en 3ième argument à `dispatch` et `commit`. + ``` js -// modules/todos.js -import * as types from '../types' +modules: { + foo: { + namespaced: true, -// on définit les getters, actions et mutations en utilisant des noms préfixés -const todosModule = { - state: { todos: [] }, + getters: { + // Les `getters` sont localisés dans le module des accesseurs + // vous pouvez utiliser `rootGetters` via le 4ième argument des accesseurs + someGetter (state, getters, rootState, rootGetters) { + getters.someOtherGetter // -> 'foo/someOtherGetter' + rootGetters.someOtherGetter // -> 'someOtherGetter' + }, + someOtherGetter: state => { ... } + }, - getters: { - [types.DONE_COUNT] (state) { - // ... - } - }, + actions: { + // les actions et mutations sont aussi localisées pour ce module + // elles vont accepter une option `root` pour la racine des actions et mutations. + someAction ({ dispatch, commit, getters, rootGetters }) { + getters.someGetter // -> 'foo/someGetter' + rootGetters.someGetter // -> 'someGetter' - actions: { - [types.FETCH_ALL] (context, payload) { - // ... - } - }, + dispatch('someOtherAction') // -> 'foo/someOtherAction' + dispatch('someOtherAction', null, { root: true }) // -> 'someOtherAction' - mutations: { - [types.TOGGLE_DONE] (state, payload) { - // ... + commit('someMutation') // -> 'foo/someMutation' + commit('someMutation', null, { root: true }) // -> 'someMutation' + }, + someOtherAction (ctx, payload) { ... } } } } ``` +#### Fonctions utilitaires liées avec espace de nom + +Quand nous lions un module sous espace de nom à un composant avec les fonctions utilitaires `mapState`, `mapGetters`, `mapActions` and `mapMutations`, cela peut être légèrement verbeux : + +``` js +computed: { + ...mapState({ + a: state => state.some.nested.module.a, + b: state => state.some.nested.module.b + }) +}, +methods: { + ...mapActions([ + 'some/nested/module/foo', + 'some/nested/module/bar' + ]) +} +``` + +Dans ces cas là, vous pouvez passer une chaîne de caractère représentant le nom d'espace en tant que premier argument aux fonctions utilitaires ainsi toutes les liaisons seront faites en utilisant le module comme contexte. Cela peut être simplifié comme ci-dessous : + +``` js +computed: { + ...mapState('some/nested/module', { + a: state => state.a, + b: state => state.b + }) +}, +methods: { + ...mapActions('some/nested/module', [ + 'foo', + 'bar' + ]) +} +``` + +#### Limitations pour les plugins des développeurs + +Vous devez faire attention au nom d'espace imprévisible pour vos modules quand vous créez un [plugin](plugins.md) qui fournit les modules et laisser les utilisateurs les ajouter au store de Vuex. Vos modules seront également sous espace de nom si l'utilisateur du plugin l'ajoute sous un module sous espace de nom. Pour vous adaptez à la situation, vous devez recevoir la valeur de l'espace de nom via vos options de plugin : + +```js +// passer la valeur d'espace de nom via une option du plugin +// et retourner une fonction de plugin Vuex +export function createPlugin (options = {}) { + return function (store) { + // ajouter l'espace de nom aux types de module + const namespace = options.namespace || '' + store.dispatch(namespace + 'pluginAction') + } +} +``` + ### Enregistrement dynamique de module Vous pouvez enregistrer un module **après** que le store ait été créé avec la méthode `store.registerModule` : ``` js +// enregistrer un module `myModule` store.registerModule('myModule', { // ... }) + +// enregistrer un module imbriqué `nested/myModule` +store.registerModule(['nested', 'myModule'], { + // ... +}) ``` -Le state du module sera disponible dans `store.state.myModule`. +L'état des modules est disponible dans `store.state.myModule` et `store.state.nested.myModule`. -L'enregistrement dynamique de module permet aux autres plugins Vue de bénéficier de la gestion de state de Vuex en attachant un module au store de l'application. Par exemple, la bibliothèque [`vuex-router-sync`](https://github.com/vuejs/vuex-router-sync) intègre vue-router avec vuex en gérant le state de la route d'application dans un module enregistré dynamiquement. +L'enregistrement dynamique de module permet aux autres plugins Vue de bénéficier de la gestion de l'état de Vuex en attachant un module au store de l'application. Par exemple, la bibliothèque [`vuex-router-sync`](https://github.com/vuejs/vuex-router-sync) intègre vue-router avec vuex en gérant l'état de la route d'application dans un module enregistré dynamiquement. Vous pouvez aussi supprimer un module enregistré dynamiquement avec `store.unregisterModule(moduleName)`. Notez que vous ne pouvez pas supprimer des modules statiques (déclarés à la création du store) avec cette méthode. + +### Ré-utiliser un module + +Parfois nous devrons créer de multiples instances d'un module pour, par exemple : + +- créer plusieurs stores qui utilisent le même module (par ex. pour [éviter les singletons d'état avec du SSR](https://ssr.vuejs.org/fr/structure.html#avoid-stateful-singletons) quand l'option `runInNewContext` est à `false` ou `'once'`) ou +- enregistrer le même module plusieurs fois dans le même store. + +Si nous utilisons un objet pour déclarer l'état du module, alors cet objet d'état sera partagé par référence et causera de contamination inter store/module quand il sera muté. + +C'est exactement le même problème qu'avec `data` dans un composant Vue. Ainsi la solution est là même, utiliser une fonction pour déclarer notre état de module (supporté par la 2.3.0+) : + +``` js +const MyReusableModule = { + state () { + return { + foo: 'bar' + } + }, + // mutations, actions, accesseurs... +} +``` \ No newline at end of file diff --git a/docs/fr/mutations.md b/docs/fr/mutations.md index 4b4b509d0..f2fbb1a5f 100644 --- a/docs/fr/mutations.md +++ b/docs/fr/mutations.md @@ -1,6 +1,6 @@ # Mutations -La seule façon de vraiment modifier le state dans un store Vuex est de commiter une mutation. Les mutations Vuex sont très similaires aux events : chaque mutation a un **type** sous forme de chaîne de caractères et un **handler**. La fonction handler est là où nous procédons aux véritables modifications du state, et elle reçoit le state en premier argument : +La seule façon de vraiment modifier l'état dans un store Vuex est d'acter une mutation. Les mutations Vuex sont très similaires aux évènements : chaque mutation a un **type** sous forme de chaîne de caractères et un **gestionnaire**. La fonction de gestion est en charge de procéder aux véritables modifications de l'état, et elle reçoit l'état en premier argument : ``` js const store = new Vuex.Store({ @@ -9,22 +9,22 @@ const store = new Vuex.Store({ }, mutations: { increment (state) { - // mutate state + // muter l'état state.count++ } } }) ``` -Vous ne pouvez pas appeler directement un handler de mutation. La façon de faire est plutôt comme un abonnement à un event : "Lorsqu'une mutation du type `increment` est déclenchée, appelle ce handler." Pour invoquer un handler de mutation, il faut appeler **store.commit** avec son type : +Vous ne pouvez pas appeler directement un gestionnaire de mutation. Le parti-pris ici est proche de l'abonnement à un évènement : « Lorsqu'une mutation du type `increment` est déclenchée, appelle ce gestionnaire. » Pour invoquer un gestionnaire de mutation, il faut appeler `store.commit` avec son type : ``` js store.commit('increment') ``` -### commiter avec un Payload +### Acter avec un argument additionnel -Vous pouvez donner un autre argument à **store.commit** pour la mutation, qui s'appelle **payload** : +Vous pouvez donner un argument additionnel (« payload ») à la fonction `store.commit` lors de la mutation : ``` js // ... @@ -38,7 +38,7 @@ mutations: { store.commit('increment', 10) ``` -Dans la plupart des cas, le payload devrait être un objet, ainsi il peut contenir plusieurs champs, et les mutations enregistrées seront également plus descriptives : +Dans la plupart des cas, l'argument additionnel devrait être un objet, ainsi il peut contenir plusieurs champs, et les mutations enregistrées seront également plus descriptives : ``` js // ... @@ -54,9 +54,9 @@ store.commit('increment', { }) ``` -### Object-Style Commit +### Acter avec un objet -Une méthode alternative pour commiter une mutation est d'utiliser directement un objet qui a une propriété `type` : +Une méthode alternative pour acter une mutation est d'utiliser directement un objet qui a une propriété `type` : ``` js store.commit({ @@ -65,7 +65,7 @@ store.commit({ }) ``` -Lors de l'utlisation de l'object-style commit, l'objet entier sera fourni comme payload aux handlers de mutation, donc le handler reste inchangé : +Lors de l'utilisation d'un objet pour acter, c'est l'objet lui-même qui ferra office d'argument pour aux gestionnaires de mutation, le gestionnaire reste donc inchangé : ``` js mutations: { @@ -77,23 +77,23 @@ mutations: { ### Les mutations suivent les règles de réactivité de Vue -Puisqu'un state de store de Vuex est rendu réactif par Vue, lorsque nous mutons le state, les composants Vue observant ce state seront automatiquement mis à jour. Cela signifie également que les mutations Vuex sont sujettes aux mêmes inconvénients que lorsqu'on travaille avec Vue : +Puisqu'un état de store de Vuex est rendu réactif par Vue, lorsque nous mutons l'état, les composants Vue observant cet état seront automatiquement mis à jour. Cela signifie également que les mutations Vuex sont sujettes aux mêmes limitations qu'avec l'utilisation de Vue seul : -1. Initialisez de préférence le state initial de votre state avec tous les champs désirés auparavant. +1. Initialisez de préférence le store initial de votre état avec tous les champs désirés auparavant. -2. Lorsque vous ajoutez de nouvelles propriétés à un Object, vous devriez soit : +2. Lorsque vous ajoutez de nouvelles propriétés à un objet, vous devriez soit : - - Utiliser `Vue.set(obj, 'newProp', 123)`, ou - + - Utiliser `Vue.set(obj, 'newProp', 123)`, ou - - Remplacer cet Object par un nouvel Object. Par exemple, en utilisant [object spread syntax](https://github.com/sebmarkbage/ecmascript-rest-spread) (stage-2), il est possible d'écrire : + - Remplacer cet objet par un nouvel objet. Par exemple, en utilisant [opérateur de décomposition](https://developer.mozilla.org/fr/docs/Web/JavaScript/Reference/Op%C3%A9rateurs/Op%C3%A9rateur_de_d%C3%A9composition) (stage-2), il est possible d'écrire : ``` js state.obj = { ...state.obj, newProp: 123 } ``` -### Utilisation de constante pour les noms de mutation +### Utilisation de constante pour les types de mutation -C'est une façon de faire régulière que d'utiliser des constantes pour les types de mutations dans diverses implémentations de Flux. Cela permet au code de bénéficier d'outils comme les linters, et écrire toutes ces constantes dans un seul fichier permet à vos collaborateurs d'avoir un aperçu de quelles mutations sont possibles dans toute l'application : +C'est une façon de faire régulière que d'utiliser des constantes pour les types de mutations dans diverses implémentations de Flux. Cela permet au code de bénéficier d'outils comme les linters (des outils d'aide à l'analyse syntaxique), et écrire toutes ces constantes dans un seul fichier permet à vos collaborateurs d'avoir un aperçu de quelles mutations sont possibles dans toute l'application : ``` js // mutation-types.js @@ -108,20 +108,20 @@ import { SOME_MUTATION } from './mutation-types' const store = new Vuex.Store({ state: { ... }, mutations: { - // we can use the ES2015 computed property name feature - // to use a constant as the function name + // nous pouvons utiliser la fonctionnalité de nom de propriété calculée + // pour utiliser une constante en tant que nom de fonction [SOME_MUTATION] (state) { - // mutate state + // muter l'état } } }) ``` -Utiliser les constantes ou non relève de la préférence personnelle — cela peut être bénéfique sur un gros projet avec beaucoup de développeurs, mais c'est totalement optionnel si vous n'aimez pas cette pratique. +Utiliser les constantes ou non relève de la préférence personnelle. Cela peut être bénéfique sur un gros projet avec beaucoup de développeurs, mais c'est totalement optionnel si vous n'aimez pas cette pratique. ### Les mutations doivent être synchrones -Une règle importante à retenir est que **les fonctions handler de mutations doivent être synchrones**. Pourquoi ? Considérons l'exemple suivant : +Une règle importante à retenir est que **les fonctions de gestion des mutations doivent être synchrones**. Pourquoi ? Considérons l'exemple suivant : ``` js mutations: { @@ -133,11 +133,11 @@ mutations: { } ``` -Maintenant imaginons que nous debuggons l'application et que nous regardons dans les logs de mutation des devtools. Pour chaque mutation enregistrée, le devtool aura besoin de capturer un instantané du state "avant" et un instantané "après". Cependant, le callback asynchrone du l'exemple ci-dessus rend l'opération impossible : le callback n'est pas encore appelé lorsque la mutation est committée, et il n'y a aucun moyen pour le devtool de savoir quand le callback sera véritablement appelé — toute mutation du state effectuée dans le callack est essentiellement intraçable ! +Maintenant imaginons que nous deboguons l'application et que nous regardons dans les logs de mutation des outils de développement (« devtools »). Pour chaque mutation enregistrée, le devtool aura besoin de capturer un instantané de l'état « avant » et un instantané « après ». Cependant, la fonction de rappel asynchrone de l'exemple ci-dessus rend l'opération impossible : la fonction de rappel n'est pas encore appelée lorsque la mutation est actée, et il n'y a aucun moyen pour le devtool de savoir quand la fonction de rappel sera véritablement appelée. Toute mutation d'état effectuée dans la fonction de rappel est essentiellement intraçable ! -### commiter des mutations dans les composants +### Acter des mutations dans les composants -Vous pouvez commiter des mutations dans les composants avec `this.$store.commit('xxx')`, ou en utilisant le helper `mapMutations` qui attache les méthodes du composant aux appels de `store.commit` (nécessite l'injection de `store` à la racine) : +Vous pouvez acter des mutations dans les composants avec `this.$store.commit('xxx')`, ou en utilisant la fonction utilitaire `mapMutations` qui attache les méthodes du composant aux appels de `store.commit` (nécessite l'injection de `store` à la racine) : ``` js import { mapMutations } from 'vuex' @@ -146,10 +146,13 @@ export default { // ... methods: { ...mapMutations([ - 'increment' // map this.increment() to this.$store.commit('increment') + 'increment' // attacher `this.increment()` à `this.$store.commit('increment')` + + // `mapMutations` supporte également les paramètres additionnels : + 'incrementBy' // attacher `this.incrementBy(amount)` à `this.$store.commit('incrementBy', amount)` ]), ...mapMutations({ - add: 'increment' // map this.add() to this.$store.commit('increment') + add: 'increment' // attacher `this.add()` à `this.$store.commit('increment')` }) } } @@ -157,12 +160,12 @@ export default { ### En avant vers les actions -L'asynchronisme combiné à la mutation du state peut rendre votre programme très difficile à comprendre. Par exemple, lorsque vous appelez deux méthodes avec toutes les deux des callbacks asynchrones qui changent le state, comment savez-vous quand elles sont appelées et quel callback est appelé en premier ? C'est exactement la raison pour laquelle nous voulons séparer les deux concepts. Avec Vuex, **les mutations sont des transactions synchrones** : +L'asynchronisme combiné à la mutation de l'état peut rendre votre programme très difficile à comprendre. Par exemple, lorsque vous appelez deux méthodes avec toutes les deux des foncitons de rappel asynchrones qui changent l'état, comment savez-vous quelle fonction de rappel est appelée en première ? C'est exactement la raison pour laquelle nous voulons séparer les deux concepts. Avec Vuex, **les mutations sont des transactions synchrones** : ``` js store.commit('increment') -// any state change that the "increment" mutation may cause -// should be done at this moment. +// n'importe quel changement d'état de « increment » par mutation +// devrait être faite de manière synchrone. ``` -Pour gérer les opérations asynchrones, présentons les [Actions](actions.md). +Pour gérer les opérations asynchrones, tournons-nous vers les [Actions](actions.md). diff --git a/docs/fr/plugins.md b/docs/fr/plugins.md index 2a77c198d..0daf01a78 100644 --- a/docs/fr/plugins.md +++ b/docs/fr/plugins.md @@ -4,10 +4,10 @@ Les stores Vuex prennent une option `plugins` qui expose des hooks pour chaque m ``` js const myPlugin = store => { - // called when the store is initialized + // appelé quand le store est initialisé store.subscribe((mutation, state) => { - // called after every mutation. - // The mutation comes in the format of { type, payload }. + // appelé après chaque mutation. + // Les mutation arrivent au format `{ type, payload }`. }) } ``` @@ -21,11 +21,11 @@ const store = new Vuex.Store({ }) ``` -### Commiter des mutations dans des plugins +### Acter des mutations dans des plugins -Les plugins ne sont pas autorisés à muter directement le state — tout comme vos composants, ils peuvent simplement déclencher des changements en committant des mutations. +Les plugins ne sont pas autorisés à muter directement l'état. Tout comme vos composants, ils peuvent simplement déclencher des changements en actant des mutations. -En commitant des mutations, un plugin peut être utilisé pour synchroniser la source de données avec le store. Par exemple, pour synchroniser la source de données d'un websocket vers le store (c'est juste un exemple artificiel, en réalité la fonction `createPlugin` peut prendre des options additionnelles pour des tâches plus complexes) : +En actant des mutations, un plugin peut être utilisé pour synchroniser la source de données avec le store. Par exemple, pour synchroniser la source de données d'une websocket vers le store (c'est juste un exemple artificiel, en réalité la fonction `createPlugin` peut prendre des options additionnelles pour des tâches plus complexes) : ``` js export default function createWebSocketPlugin (socket) { @@ -52,9 +52,9 @@ const store = new Vuex.Store({ }) ``` -### Prendre des instantanés du state +### Prendre des instantanés de l'état -Parfois un plugin peut vouloir reçevoir des "instantanés" du state, et également comparer le state post-mutation avec le state pre-mutation. Pour faire ceci, vous aurez besoin d'effectuer une deep-copy sur l'objet du state : +Parfois un plugin peut vouloir recevoir des « instantanés » de l'état, et également comparer l'état post-mutation avec l'état pré-mutation. Pour faire ceci, vous aurez besoin d'effectuer une copie complète de l'état : ``` js const myPluginWithSnapshot = store => { @@ -62,15 +62,15 @@ const myPluginWithSnapshot = store => { store.subscribe((mutation, state) => { let nextState = _.cloneDeep(state) - // compare prevState and nextState... + // comparer `prevState` et `nextState`... - // save state for next mutation + // sauver l'état pour la prochaine mutation prevState = nextState }) } ``` -**Les plugins qui peuvent prendre des instantanés ne devraient être utilisés que pendant le développement.** Lorsqu'on utilise webpack ou Browserify, on peut laisser nos devtools s'occuper de ça pour nous : +**Les plugins qui peuvent prendre des instantanés ne devraient être utilisés que pendant le développement.** Lorsqu'on utilise webpack ou Browserify, on peut laisser nos outils de développement (« devtools ») s'occuper de ça pour nous : ``` js const store = new Vuex.Store({ @@ -83,11 +83,11 @@ const store = new Vuex.Store({ Le plugin sera utilisé par défaut. Pour la production, vous aurez besoin de [DefinePlugin](https://webpack.github.io/docs/list-of-plugins.html#defineplugin) pour webpack ou de [envify](https://github.com/hughsk/envify) pour Browserify pour convertir la valeur de `process.env.NODE_ENV !== 'production'` à `false` pour le build final. -### Plugin logger intégré +### Plugin de logs intégré > Si vous utilisez [vue-devtools](https://github.com/vuejs/vue-devtools) vous n'avez probablement pas besoin de ça. -Vuex fournit un plugin de logger à des fins de debugging : +Vuex fournit un plugin de logs à des fins de débogage : ``` js import createLogger from 'vuex/dist/logger' @@ -103,23 +103,23 @@ La fonction `createLogger` prend quelques options : const logger = createLogger({ collapsed: false, // auto-expand logged mutations filter (mutation, stateBefore, stateAfter) { - // returns true if a mutation should be logged - // `mutation` is a { type, payload } + // retourne `true` si une mutation devrait être logguée + // `mutation` est un `{ type, payload }` return mutation.type !== "aBlacklistedMutation" }, transformer (state) { - // transform the state before logging it. - // for example return only a specific sub-tree + // transforme l'état avant de le logguer. + // retourne par exemple seulement un sous-arbre spécifique return state.subTree }, mutationTransformer (mutation) { - // mutations are logged in the format of { type, payload } - // we can format it any way we want. + // les mutations sont logguées au format `{ type, payload }` + // nous pouvons les formater comme nous le souhaitons. return mutation.type } }) ``` -Le fichier logger peut aussi être inclus directement via une balise `script`, et exposera la fonction `createVuexLogger` globalement. +Le fichier de logs peut aussi être inclus directement via une balise `script`, et exposera la fonction `createVuexLogger` globalement. -Notez que le plugin logger peut prendre des instantanés du state, ne l'utilisez donc que durant le développement. +Notez que le plugin de logs peut prendre des instantanés de l'état, ne l'utilisez donc que durant le développement. diff --git a/docs/fr/state.md b/docs/fr/state.md index b470ede1a..b9435eee3 100644 --- a/docs/fr/state.md +++ b/docs/fr/state.md @@ -1,14 +1,14 @@ # State -### Single State Tree +### Arbre d'état unique -Vuex utilise un **single state tree** — cet unique objet contient tout le state au niveau applicatif et sert de "source unique de vérité". Cela signifie également que vous n'aurez qu'un seul store pour chaque application. Un _single state tree_ rend rapide la localisation d'une partie de state spécifique, et nous permet de facilement prendre des instantanés du state actuel de l'application à des fins de debugging. +Vuex utilise un **arbre d'état unique**, c'est-à-dire que cet unique objet contient tout l'état au niveau applicatif et sert de « source de vérité unique ». Cela signifie également que vous n'aurez qu'un seul store pour chaque application. Un arbre d'état unique rend rapide la localisation d'une partie spécifique de l'état et permet de facilement prendre des instantanés de l'état actuel de l'application à des fins de débogage. -Le _single state tree_ n'entre pas en conflit avec la modularité — dans les prochains chapitres, nous examinerons comment séparer votre state et vos mutations dans des sous-modules. +L'arbre d'état unique n'entre pas en conflit avec la modularité. Dans les prochains chapitres, nous examinerons comment séparer votre état et vos mutations dans des sous-modules. -### Récupérer le state Vuex dans des composants Vue +### Récupération d'état Vuex dans des composants Vue -Alors, comment affichons-nous le state du store dans nos composants Vue ? Puisque les stores Vuex sont réactifs, la façon la plus simple d'y "récupérer" le state est de simplement retourner une partie du state depuis une [computed property](http://vuejs.org/guide/computed.html) : +Alors, comment affichons-nous l'état du store dans nos composants Vue ? Puisque les stores Vuex sont réactifs, la façon la plus simple d'y « récupérer » l'état est tout simplement de retourner une partie de l'état depuis une [une propriété calculée](http://fr.vuejs.org/guide/computed.html) : ``` js // créons un composant Counter @@ -22,16 +22,16 @@ const Counter = { } ``` -Lorsque `store.state.count` change, cela entraînera la ré-évaluation de la computed property, et déclenchera les actions DOM associées. +Lorsque `store.state.count` change, cela entraînera la ré-évaluation de la propriété calculée, et déclenchera les actions associées au DOM. -Cependant, ce pattern oblige le composant à compter sur le singleton global du store. Lorsqu'on utilise un système de module, il est nécessaire d'importer le store dans tous les composants qui utilisent le state du store, et il est également nécessaire de créer un mock lorsque l'on teste le composant. +Cependant, ce modèle oblige le composant à compter sur le singleton global du store. Lorsqu'on utilise un système de module, il est nécessaire d'importer le store dans tous les composants qui utilisent l'état du store, et il est également nécessaire de le simuler lorsque l'on teste le composant. -Vuex fournit un méchanisme pour "injecter" le store dans tous les composants enfants du composant racine avec l'option `store` (activée par `Vue.use(Vuex)`) : +Vuex fournit un méchanisme pour « injecter » le store dans tous les composants enfants du composant racine avec l'option `store` (activée par `Vue.use(Vuex)`) : ``` js const app = new Vue({ el: '#app', - // fournit le store avec l'option "store". + // fournit le store avec l'option `store`. // cela injectera l'instance du store dans tous les composants enfants. store, components: { Counter }, @@ -43,7 +43,7 @@ const app = new Vue({ }) ``` -En fournissant l'option `store` à l'instance racine, le store sera injecté dans tous les composants enfants de la racine et sera disponible sur ceux-ci avec `this.$store`. Mettons à jours notre implémentation de `Counter` : +En fournissant l'option `store` à l'instance racine, le store sera injecté dans tous les composants enfants de la racine et sera disponible dans ces derniers avec `this.$store`. Mettons à jour notre implémentation de `Counter` : ``` js const Counter = { @@ -56,12 +56,12 @@ const Counter = { } ``` -### Le helper `mapState` +### La fonction utilitaire `mapState` -Lorsqu'un composant a besoin d'utiliser plusieurs propriétés ou getters du state du store, déclarer toutes ces computed properties peut devenir répétitif et verbeux. Afin de palier à ça, nous pouvons utiliser le helper `mapState` qui génère des fonctions getters pour nous et nous épargne quelques coups de clavier : +Lorsqu'un composant a besoin d'utiliser plusieurs accesseurs ou propriétés de l'état du store, déclarer toutes ces propriétés calculées peut devenir répétitif et verbeux. Afin de palier à ça, nous pouvons utiliser la fonction utilitaire `mapState` qui génère des fonctions d'accession pour nous et nous épargne quelques coups de clavier : ``` js -// dans la version standalone, les helpers sont exposés comme Vuex.mapState +// dans la version complète, des fonctions utilitaires sont exposées tel que `Vuex.mapState` import { mapState } from 'vuex' export default { @@ -73,7 +73,7 @@ export default { // passer la valeur littérale 'count' revient à écrire `state => state.count` countAlias: 'count', - // pour accéder au state local avec `this`, une fonction normale doit être utilisée + // pour accéder à l'état local avec `this`, une fonction normale doit être utilisée countPlusLocalState (state) { return state.count + this.localCount } @@ -81,29 +81,29 @@ export default { } ``` -Il est également possible de fournir un tableau de chaînes de caractères à `mapState` lorsque le nom de la propriété du state du store est la même que celui du composant. +Il est également possible de fournir un tableau de chaînes de caractères à `mapState` lorsque le nom de la propriété de l'état du store est la même que celui du composant. ``` js computed: mapState([ - // attacher this.count à store.state.count + // attacher `this.count` à `store.state.count` 'count' ]) ``` -### Object Spread Operator +### Opérateur de décomposition -Notez que `mapState` renvoie un objet. Comment l'utiliser en complément des autres computed properties locales ? Normalement, il faudrait utiliser un outil pour fusionner les multiples objets en un seul afin de passer cet objet final à `computed`. Cependant avec le [object spread operator](https://github.com/sebmarkbage/ecmascript-rest-spread) (qui est une proposition stage-3 ECMASCript), nous pouvons grandement simplifier la syntaxe : +Notez que `mapState` renvoie un objet. Comment l'utiliser en complément des autres propriétés calculées locales ? Normalement, il faudrait utiliser un outil pour fusionner les multiples objets en un seul afin de passer cet objet final à `computed`. Cependant avec l'[opérateur de décomposition](https://developer.mozilla.org/fr/docs/Web/JavaScript/Reference/Op%C3%A9rateurs/Op%C3%A9rateur_de_d%C3%A9composition) (qui est une proposition stage-3 ECMASCript), nous pouvons grandement simplifier la syntaxe : ``` js computed: { localComputed () { /* ... */ }, - // rajouter cet objet dans l'objet `computed` avec l'object spread operator + // rajouter cet objet dans l'objet `computed` avec l'opérateur de décomposition ...mapState({ // ... }) } ``` -### Les composants peuvent toujours avoir un state local +### Les composants peuvent toujours avoir un état local -Utiliser Vuex ne signifie pas que vous devez mettre **tout** votre state dans Vuex. Bien que le fait de mettre plus de state dans Vuex rende vos mutations de state plus explicites et plus debuggables, parfois il peut aussi rendre le code plus verbeux et indirect. Si une partie de state appartient directement à un seul composant, il est parfaitement sain de la laisser dans le state local. Assurez vous de prendre en compte les avantages et inconvénients d'une telle décision afin de vous adaptez le mieux aux besoins de votre application. +Utiliser Vuex ne signifie pas que vous devez mettre **tout** votre état dans Vuex. Bien que le fait de mettre plus d'état dans Vuex rende vos mutation d'état plus explicites et plus débogable, parfois il peut aussi rendre le code plus verbeux et indirect. Si une partie de l'état appartient directement à un seul composant, il est parfaitement sain de la laisser dans l'état local. Assurez vous de prendre en compte les avantages et inconvénients d'une telle décision afin de vous adapter au mieux aux besoins de votre application. diff --git a/docs/fr/strict.md b/docs/fr/strict.md index 4989bf3b4..a2720648d 100644 --- a/docs/fr/strict.md +++ b/docs/fr/strict.md @@ -1,6 +1,6 @@ -# Strict Mode +# Mode strict -Pour activer le mode strict, passez simplement l'option `strict: true` lorsque vous créez un store Vuex : +Pour activer le mode strict, passez simplement l'option `strict: true` pendant la création d'un store Vuex : ``` js const store = new Vuex.Store({ @@ -9,11 +9,11 @@ const store = new Vuex.Store({ }) ``` -En mode strict, lorsque le state Vuex est modifié en dehors des handlers de mutation, une erreur sera lancée. Cela permet de s'assurer que toutes les mutations du state peuvent être explicitement tracées par les outils de debugging. +En mode strict, lorsque l'état de Vuex est modifié en dehors des gestionnaires de mutation, une erreur sera lancée. Cela permet de s'assurer que toutes les mutations de l'état peuvent être explicitement tracées par les outils de débogage. -### Développement vs. Production +### Développement vs. production -**N'activez pas le mode strict lorsque vous déployez en production !** Le mode strict lance une observation récursive du state tree pour détecter des mutations inappropriées — assurrez-vous de l'avoir désactivé en production pour éviter un coût sur les performances. +**N'activez pas le mode strict lorsque vous déployez en production !** Le mode strict lance une observation récursive de l'arbre d'état pour détecter des mutations inappropriées. Assurrez-vous de l'avoir désactivé en production pour éviter un coût sur les performances. Tout comme les plugins, nous pouvons laisser nos outils de build gérer ça : diff --git a/docs/fr/structure.md b/docs/fr/structure.md index 41c94d3ed..3469b301e 100644 --- a/docs/fr/structure.md +++ b/docs/fr/structure.md @@ -1,14 +1,14 @@ # Structure d'une application -Vuex ne vous restreint pas vraiment dans la façon dont vous voulez structurer votre code. Il impose plutôt un set de principes de haut niveau : +Vuex ne vous restreint pas quand à la structure de code à utiliser. Il impose plutôt de respecter des principes de haut niveau : -1. Le state d'application est centralisé dans le store. +1. L'état de l'application est centralisé dans le store. -2. La seule façon de muter le state est de commiter des **mutations**, qui sont des transactions synchrones. +2. La seule façon de muter l'état est d'acter des **mutations**, qui sont des transactions synchrones. 3. La logique asynchrone doit être composée et encapsulée dans des **actions**. -Tant que vous suivez ces règles, c'est à vous de structurer votre projet. Si votre fichier de store devient trop gros, commencez simplement par séparer les actions, mutations et getters dans des fichiers séparés. +Tant que vous suivez ces règles, c'est à vous de structurer votre projet. Si votre fichier de store devient trop gros, commencez dès lors à séparer les actions, mutations et accesseurs dans des fichiers séparés. Pour une application non-triviale, nous aurons probablement besoin de faire appel à des modules. Voici un exemple de structure de projet : @@ -16,17 +16,17 @@ Pour une application non-triviale, nous aurons probablement besoin de faire appe ├── index.html ├── main.js ├── api -│   └── ... # abstractions for making API requests +│   └── ... # abstraction pour faire des requêtes par API ├── components │   ├── App.vue │   └── ... └── store - ├── index.js # Là où l'on assemble nos modules et exportons le store - ├── actions.js # Actions racine - ├── mutations.js # Mutations racine + ├── index.js # là où l'on assemble nos modules et exportons le store + ├── actions.js # actions racine + ├── mutations.js # mutations racine └── modules -    ├── cart.js # cart module -    └── products.js # products module +    ├── cart.js # module de panier +    └── products.js # module de produit ``` -Vous pouvez jeter à un œil à [l'exemple Shopping Cart](https://github.com/vuejs/vuex/tree/dev/examples/shopping-cart). +Vous pouvez jeter à un œil à l'[exemple de panier d'achat](https://github.com/vuejs/vuex/tree/dev/examples/shopping-cart). diff --git a/docs/fr/testing.md b/docs/fr/testing.md index 65b0087e2..28cfbb756 100644 --- a/docs/fr/testing.md +++ b/docs/fr/testing.md @@ -1,6 +1,6 @@ # Tests -Les parties principales que l'on veut couvrir par des tests unitaires en Vuex sont les mutations et les actions. +Les parties principales que l'on veut couvrir par des tests unitaires avec Vuex sont les mutations et les actions. ### Tester les mutations @@ -9,7 +9,7 @@ Les mutations sont très simples à tester, puisque ce sont de simples fonctions ``` js const state = { ... } -// export mutations as a named export +// exporter les mutations en tant qu'export nommé export const mutations = { ... } export default new Vuex.Store({ @@ -18,7 +18,7 @@ export default new Vuex.Store({ }) ``` -Exemple de test de mutation utilisant Mocha + Chai (vous pouvez utiliser n'importe quel framework/bibliothèque d'assertion selon votre préférence) : +Exemple de test de mutation utilisant Mocha + Chai (vous pouvez utiliser n'importe quel framework/bibliothèque d'assertion selon vos préférences) : ``` js // mutations.js @@ -32,16 +32,16 @@ export const mutations = { import { expect } from 'chai' import { mutations } from './store' -// destructure assign mutations +// assignement des mutations par déstructuration const { increment } = mutations describe('mutations', () => { it('INCREMENT', () => { - // mock state + // état simulé const state = { count: 0 } - // apply mutation + // appliquer la mutation increment(state) - // assert result + // tester le résultat expect(state.count).to.equal(1) }) }) @@ -49,7 +49,7 @@ describe('mutations', () => { ### Tester les actions -Les actions sont un peu plus compliquées car elles peuvent faire appel à des APIs externes. Lorsque l'on teste des actions, on a souvent besoin de faire du mocking — par exemple, on peut abstraire l'appel API dans un service et mocker ce service dans nos tests. Afin de mocker facilement les dépendances, on peut utiliser webpack et [inject-loader](https://github.com/plasticine/inject-loader) pour regrouper nos fichiers de test. +Les actions sont un peu plus compliquées car elles peuvent faire appel à des APIs externes. Lorsque l'on teste des actions, on a souvent besoin de faire plusieurs niveaux de simulation. Par exemple, on peut abstraire l'appel API dans un service et simuler ce service dans nos tests. Afin de simuler facilement les dépendances, on peut utiliser webpack et [inject-loader](https://github.com/plasticine/inject-loader) pour regrouper nos fichiers de test. Exemple de test d'une action asynchrone : @@ -68,28 +68,28 @@ export const getAllProducts = ({ commit }) => { ``` js // actions.spec.js -// use require syntax for inline loaders. -// with inject-loader, this returns a module factory -// that allows us to inject mocked dependencies. +// utilisation de la syntaxe `require` pour les loaders. +// avec inject-loader, cela retourne un module de fabrique +// cela nous permet d'injecter les dépendances simulées. import { expect } from 'chai' const actionsInjector = require('inject!./actions') -// create the module with our mocks +// créer un module avec nos simulations const actions = actionsInjector({ '../api/shop': { getProducts (cb) { setTimeout(() => { - cb([ /* mocked response */ ]) + cb([ /* réponse simulée */ ]) }, 100) } } }) -// helper for testing action with expected mutations +// fonction utilitaire pour tester des actions avec les mutations attendues const testAction = (action, args, state, expectedMutations, done) => { let count = 0 - // mock commit + // acter une simulation const commit = (type, payload) => { const mutation = expectedMutations[count] @@ -108,10 +108,10 @@ const testAction = (action, args, state, expectedMutations, done) => { } } - // call the action with mocked store and arguments + // appeler l'action avec le store simulé et les arguments action({ commit, state }, ...args) - // check if no mutations should have been dispatched + // vérifier qu'aucune mutations n'ai été propagée if (expectedMutations.length === 0) { expect(count).to.equal(0) done() @@ -128,11 +128,11 @@ describe('actions', () => { }) ``` -### Tester les getters +### Tester les accesseurs -Si vos getters font des calculs compliqués, il peut être judicieux de les tester. Les getters sont également très simples à tester, pour les mêmes raisons que les mutations. +Si vos accesseurs font des calculs compliqués, il peut être judicieux de les tester. Les accesseurs sont également très simples à tester, pour les mêmes raisons que les mutations. -Exemple de test d'un getter : +Exemple de test d'un accesseur : ``` js // getters.js @@ -152,7 +152,7 @@ import { getters } from './getters' describe('getters', () => { it('filteredProducts', () => { - // mock state + // état simulé const state = { products: [ { id: 1, title: 'Apple', category: 'fruit' }, @@ -160,13 +160,13 @@ describe('getters', () => { { id: 3, title: 'Carrot', category: 'vegetable' } ] } - // mock getter + // accesseur simulé const filterCategory = 'fruit' - // get the result from the getter + // obterir le résultat depuis l'accesseur const result = getters.filteredProducts(state, { filterCategory }) - // assert the result + // tester le résultat expect(result).to.deep.equal([ { id: 1, title: 'Apple', category: 'fruit' }, { id: 2, title: 'Orange', category: 'fruit' } @@ -177,9 +177,9 @@ describe('getters', () => { ### Lancer les tests -Si vos mutations et actions sont écrites comme il se doit, les tests ne devraient pas avoir de dépendance directe sur les APIs navigateur après un mocking préalable. Cela signifie que vous pouvez simplement regrouper les tests avec webpack et les lancer directement dans Node. De façon alternative, vous pouvez utiliser `mocha-loader` ou Karma + `karma-webpack` afin d'effectuer les tests dans des vrais navigateurs. +Si vos mutations et actions sont écrites comme il se doit, les tests ne devraient pas avoir de dépendance directe sur les APIs navigateur après une simulation préalable. Cela signifie que vous pouvez simplement regrouper les tests avec webpack et les lancer directement dans Node.js. De façon alternative, vous pouvez utiliser `mocha-loader` ou Karma + `karma-webpack` afin d'effectuer les tests dans des vrais navigateurs. -#### Lancer dans Node +#### Lancer dans Node.js Créez la configuration webpack suivante (ainsi que le fichier [`.babelrc`](https://babeljs.io/docs/usage/babelrc/) qui correspond) : @@ -212,10 +212,10 @@ mocha test-bundle.js #### Lancer dans un navigateur -1. Installez `mocha-loader` +1. Installez `mocha-loader`. 2. Changez l'option `entry` de la configuration webpack ci-dessus pour `'mocha!babel!./test.js'`. 3. Démarrez `webpack-dev-server` en utilisant cette configuration. -4. Pointez votre navigateur sur `localhost:8080/webpack-dev-server/test-bundle`. +4. Rendez-vous avec votre navigateur sur `localhost:8080/webpack-dev-server/test-bundle`. #### Lancer dans un navigateur avec Karma + karma-webpack From 3a9a919efad4532472d97eb6c9218c672bf2d248 Mon Sep 17 00:00:00 2001 From: Bruno Lesieur Date: Mon, 17 Jul 2017 08:47:20 +0200 Subject: [PATCH 02/21] Update `NPM` to `npm` Signed-off-by: Bruno Lesieur --- docs/fr/installation.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/fr/installation.md b/docs/fr/installation.md index 508cdaef9..6e12abeb1 100644 --- a/docs/fr/installation.md +++ b/docs/fr/installation.md @@ -5,7 +5,7 @@ [https://unpkg.com/vuex](https://unpkg.com/vuex) -[Unpkg.com](https://unpkg.com) fournit des liens CDN basés sur NPM. Le lien ci-dessus pointera toujours vers la dernière release sur NPM. Vous pouvez aussi utiliser un tag ou une version spécifique via une URL comme `https://unpkg.com/vuex@2.0.0`. +[Unpkg.com](https://unpkg.com) fournit des liens CDN basés sur npm. Le lien ci-dessus pointera toujours vers la dernière release sur npm. Vous pouvez aussi utiliser un tag ou une version spécifique via un URL comme `https://unpkg.com/vuex@2.0.0`. Incluez `vuex` après Vue et l'installation sera automatique : @@ -15,7 +15,7 @@ Incluez `vuex` après Vue et l'installation sera automatique : ``` -### NPM +### npm ``` bash npm install vuex --save From 18997e9b7686a9075eb47770e9491905ed2c12c8 Mon Sep 17 00:00:00 2001 From: Bruno Lesieur Date: Thu, 20 Jul 2017 11:20:12 +0200 Subject: [PATCH 03/21] la devient le (@flyusfly) Signed-off-by: Bruno Lesieur --- docs/fr/state.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/fr/state.md b/docs/fr/state.md index b9435eee3..8450eb3d4 100644 --- a/docs/fr/state.md +++ b/docs/fr/state.md @@ -81,7 +81,7 @@ export default { } ``` -Il est également possible de fournir un tableau de chaînes de caractères à `mapState` lorsque le nom de la propriété de l'état du store est la même que celui du composant. +Il est également possible de fournir un tableau de chaînes de caractères à `mapState` lorsque le nom de la propriété de l'état du store est le même que celui du composant. ``` js computed: mapState([ From cc904c298f76b3e16c22a3d693f48f4413cdd171 Mon Sep 17 00:00:00 2001 From: Bruno Lesieur Date: Mon, 14 Aug 2017 09:58:36 +0200 Subject: [PATCH 04/21] New core-concepts.md file Signed-off-by: Bruno Lesieur --- docs/fr/core-concepts.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 docs/fr/core-concepts.md diff --git a/docs/fr/core-concepts.md b/docs/fr/core-concepts.md new file mode 100644 index 000000000..60ba7888b --- /dev/null +++ b/docs/fr/core-concepts.md @@ -0,0 +1,12 @@ +# Concepts de base + +Nous allons apprendre les concepts de base dans Vuex avec ce chapitre. Ces concepts sont + - [État](state.md) + - [Accesseurs](getters.md) + - [Mutations](mutations.md) + - [Actions](actions.md) + - [Modules](modules.md) + +Une compréhension profonde de ces concepts est essentielle pour l'utilisation de Vuex. + +C'est parti. From e49597da10d01368ca6bde73c1ea5d7969340492 Mon Sep 17 00:00:00 2001 From: Bruno Lesieur Date: Tue, 15 Aug 2017 15:51:48 +0200 Subject: [PATCH 05/21] Update book.json using a copy/past from en version Signed-off-by: Bruno Lesieur --- docs/fr/book.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/fr/book.json b/docs/fr/book.json index 428c98162..f9691c3c9 120000 --- a/docs/fr/book.json +++ b/docs/fr/book.json @@ -4,7 +4,7 @@ "pluginsConfig": { "edit-link": { "base": "https://github.com/vuejs/vuex/tree/dev/docs", - "label": "Éditer cette page" + "label": "Éditer la page" }, "github": { "url": "https://github.com/vuejs/vuex/" From bc94448ba4d5d0ca03e950033b2b23b4b21c682a Mon Sep 17 00:00:00 2001 From: Bruno Lesieur Date: Tue, 15 Aug 2017 15:56:32 +0200 Subject: [PATCH 06/21] Remove book.json Signed-off-by: Bruno Lesieur --- docs/fr/book.json | 19 ------------------- 1 file changed, 19 deletions(-) delete mode 120000 docs/fr/book.json diff --git a/docs/fr/book.json b/docs/fr/book.json deleted file mode 120000 index f9691c3c9..000000000 --- a/docs/fr/book.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "gitbook": "2.x.x", - "plugins": ["edit-link", "prism", "-highlight", "github"], - "pluginsConfig": { - "edit-link": { - "base": "https://github.com/vuejs/vuex/tree/dev/docs", - "label": "Éditer la page" - }, - "github": { - "url": "https://github.com/vuejs/vuex/" - } - }, - "links": { - "sharing": { - "facebook": false, - "twitter": false - } - } -} From 690f1ff10ecbcaac5274fccbb35bd9a825ec3dba Mon Sep 17 00:00:00 2001 From: Bruno Lesieur Date: Tue, 15 Aug 2017 15:58:17 +0200 Subject: [PATCH 07/21] Add book.json Signed-off-by: Bruno Lesieur --- docs/fr/book.json | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 docs/fr/book.json diff --git a/docs/fr/book.json b/docs/fr/book.json new file mode 100644 index 000000000..428c98162 --- /dev/null +++ b/docs/fr/book.json @@ -0,0 +1,19 @@ +{ + "gitbook": "2.x.x", + "plugins": ["edit-link", "prism", "-highlight", "github"], + "pluginsConfig": { + "edit-link": { + "base": "https://github.com/vuejs/vuex/tree/dev/docs", + "label": "Éditer cette page" + }, + "github": { + "url": "https://github.com/vuejs/vuex/" + } + }, + "links": { + "sharing": { + "facebook": false, + "twitter": false + } + } +} From e2f8609b6db6d364fee7c300ff05308e925e75a2 Mon Sep 17 00:00:00 2001 From: Bruno Lesieur Date: Thu, 24 Aug 2017 10:06:13 +0200 Subject: [PATCH 08/21] Add `createNamespacedHelpers` french translation Signed-off-by: Bruno Lesieur --- docs/fr/api.md | 46 +++++++++++++++++++++++++--------------------- docs/fr/modules.md | 25 +++++++++++++++++++++++++ 2 files changed, 50 insertions(+), 21 deletions(-) diff --git a/docs/fr/api.md b/docs/fr/api.md index eb0b2034c..448777db1 100644 --- a/docs/fr/api.md +++ b/docs/fr/api.md @@ -16,7 +16,7 @@ const store = new Vuex.Store({ ...options }) L'objet d'état racine pour le store Vuex. - [Détails](state.md) + [Plus de détails](state.md) - **mutations** @@ -24,7 +24,7 @@ const store = new Vuex.Store({ ...options }) Enregistrer les mutations sur le store. La fonction gestionnaire reçoit toujours `state` comme premier argument (sera l'état local du module si défini dans un module), et reçoit le `payload` en second argument s'il y en a un. - [Détails](mutations.md) + [Plus de détails](mutations.md) - **actions** @@ -42,7 +42,7 @@ const store = new Vuex.Store({ ...options }) } ``` - [Détails](actions.md) + [Plus de détails](actions.md) - **getters** @@ -66,7 +66,7 @@ const store = new Vuex.Store({ ...options }) Les accesseurs enregistrés sont exposés sur `store.getters`. - [Détails](getters.md) + [Plus de détails](getters.md) - **modules** @@ -90,7 +90,7 @@ const store = new Vuex.Store({ ...options }) Chaque module peut contenir `state` et `mutations`, tout comme les options racine. L'état d'un module sera attaché à l'état racine du store en utilisant la clé du module. Les mutations et accesseurs d'un module recevront seulement l'état local du module en premier argument au lieu de l'état racine, et le `context.state` des actions du module pointeront également vers l'état local. - [Détails](modules.md) + [Plus de détails](modules.md) - **plugins** @@ -98,7 +98,7 @@ const store = new Vuex.Store({ ...options }) Un tableau de fonctions plugins qui seront appliquées au store. Un plugin reçoit simplement le store comme seul argument et peut soit écouter les mutations (pour la persistence de données, les logs ou le débogage) ou propager des mutations (pour les données internes, c.-à-d. websockets ou observables). - [Détails](plugins.md) + [Plus de détails](plugins.md) - **strict** @@ -107,7 +107,7 @@ const store = new Vuex.Store({ ...options }) Force le store Vuex en mode strict. En mode strict, toute mutation de l'état en dehors des gestionnaires de mutation lancera une erreur. - [Détails](strict.md) + [Plus de détails](strict.md) ### Propriétés d'instance de `Vuex.Store` @@ -127,11 +127,11 @@ const store = new Vuex.Store({ ...options }) - **`commit(type: string, payload?: any, options?: Object) | commit(mutation: Object, options?: Object)`** - Acter une mutation. `options` peut avoir `root: true` ce qui permet d'acter des mutations racines dans des [modules sous espace de nom](modules.md#namespacing). [Détails](mutations.md) + Acter une mutation. `options` peut avoir `root: true` ce qui permet d'acter des mutations racines dans des [modules sous espace de nom](modules.md#namespacing). [Plus de détails](mutations.md) - **`dispatch(type : string, payload?: any, options?: Object) | dispatch(action: Object, options?: Object)`** - Propager une action. Retourne la valeur renvoyée par le gestionnaire d'action déclenché, ou une Promesse si plusieurs gestionnaires ont été déclenchés. [Détails](actions.md) + Propager une action. Retourne la valeur renvoyée par le gestionnaire d'action déclenché, ou une Promesse si plusieurs gestionnaires ont été déclenchés. [Plus de détails](actions.md) - **`replaceState(state: Object)`** @@ -154,42 +154,46 @@ const store = new Vuex.Store({ ...options }) }) ``` - Utilisé plus communément dans les plugins. [Détails](plugins.md) + Utilisé plus communément dans les plugins. [Plus de détails](plugins.md) - **`registerModule(path: string | Array, module: Module)`** - Enregistrer un module dynamique. [Détails](modules.md#enregistrement-dynamique-de-module) + Enregistrer un module dynamique. [Plus de détails](modules.md#enregistrement-dynamique-de-module) - **`unregisterModule(path: string | Array)`** - Supprimer un module dynamique. [Détails](modules.md#enregistrement-dynamique-de-module) + Supprimer un module dynamique. [Plus de détails](modules.md#enregistrement-dynamique-de-module) - **`hotUpdate(newOptions: Object)`** - Remplacement à la volée des nouvelles actions et mutations. [Détails](hot-reload.md) + Remplacement à la volée des nouvelles actions et mutations. [Plus de détails](hot-reload.md) ### Fonctions utilitaires d'attachement au composant - **`mapState(namespace?: string, map: Array | Object): Object`** - Créer des propriétés calculées qui retournent le sous arbre du store Vuex au composant. [Détails](state.md#le-helper-mapstate) + Créer des propriétés calculées qui retournent le sous arbre du store Vuex au composant. [Plus de détails](state.md#le-helper-mapstate) - Le premier argument peut être de façon optionnel une chaîne d'espace de nom. [Details](modules.md#Fonctions-utilitaires-liées-avec-espace-de-nom) + Le premier argument peut être de façon optionnel une chaîne d'espace de nom. [Plus de détails](modules.md#Fonctions-utilitaires-liées-avec-espace-de-nom) - **`mapGetters(namespace?: string, map: Array | Object): Object`** - Créer des propriétés calculées qui retournent la valeur calculée d'un accesseur. [Détails](getters.md#la-function-utilitaire-mapgetters) + Créer des propriétés calculées qui retournent la valeur calculée d'un accesseur. [Plus de détails](getters.md#la-function-utilitaire-mapgetters) - Le premier argument peut être de façon optionnel une chaîne d'espace de nom. [Details](modules.md#Fonctions-utilitaires-liées-avec-espace-de-nom) + Le premier argument peut être de façon optionnel une chaîne d'espace de nom. [Plus de détails](modules.md#Fonctions-utilitaires-liées-avec-espace-de-nom) - **`mapActions(namespace?: string, map: Array | Object): Object`** - Créer des méthodes de composant qui propagent une action. [Détails](actions.md#propager-des-actions-dans-les-composants) + Créer des méthodes de composant qui propagent une action. [Plus de détails](actions.md#propager-des-actions-dans-les-composants) - Le premier argument peut être de façon optionnel une chaîne d'espace de nom. [Details](modules.md#Fonctions-utilitaires-liées-avec-espace-de-nom) + Le premier argument peut être de façon optionnel une chaîne d'espace de nom. [Plus de détails](modules.md#Fonctions-utilitaires-liées-avec-espace-de-nom) - **`mapMutations(namespace?: string, map: Array | Object): Object`** - Créer des méthodes de composant qui actent une mutation. [Détails](mutations.md#acter-des-mutations-dans-les-composants) + Créer des méthodes de composant qui actent une mutation. [Plus de détails](mutations.md#acter-des-mutations-dans-les-composants) - Le premier argument peut être de façon optionnel une chaîne d'espace de nom. [Details](modules.md#Fonctions-utilitaires-liées-avec-espace-de-nom) + Le premier argument peut être de façon optionnel une chaîne d'espace de nom. [Plus de détails](modules.md#Fonctions-utilitaires-liées-avec-espace-de-nom) + +- **`createNamespacedHelpers(namespace: string): Object`** + + Créer des fonctions utilitaires liées avec espace de nom. L'objet retourné contient `mapState`, `mapGetters`, `mapActions` et `mapMutations` qui sont liées à l'espace de nom fourni. [Plus de détails](modules.md#fonctions-utilitaires-liées-avec-espace-de-nom) diff --git a/docs/fr/modules.md b/docs/fr/modules.md index f6d2dea71..4f16913a8 100644 --- a/docs/fr/modules.md +++ b/docs/fr/modules.md @@ -206,6 +206,31 @@ methods: { } ``` +De plus, vous pouvez créer des fonctions utilitaires liées avec espace de nom en utilisant `createNamespacedHelpers`. Cela retourne un objet qui a les nouvelles fonctions utilitaires ratachées à la valeur d'espace de nom fournie : + +``` js +import { createNamespacedHelpers } from 'vuex' + +const { mapState, mapActions } = createNamespacedHelpers('some/nested/module') + +export default { + computed: { + // vérifie dans `some/nested/module` + ...mapState({ + a: state => state.a, + b: state => state.b + }) + }, + methods: { + // vérifie dans `some/nested/module` + ...mapActions([ + 'foo', + 'bar' + ]) + } +} +``` + #### Limitations pour les plugins des développeurs Vous devez faire attention au nom d'espace imprévisible pour vos modules quand vous créez un [plugin](plugins.md) qui fournit les modules et laisser les utilisateurs les ajouter au store de Vuex. Vos modules seront également sous espace de nom si l'utilisateur du plugin l'ajoute sous un module sous espace de nom. Pour vous adaptez à la situation, vous devez recevoir la valeur de l'espace de nom via vos options de plugin : From 2d402b8b54350f2cbca5ecde44f376bb517c93dd Mon Sep 17 00:00:00 2001 From: Bruno Lesieur Date: Tue, 12 Sep 2017 12:58:29 +0200 Subject: [PATCH 09/21] Change http link to https Signed-off-by: Bruno Lesieur --- docs/fr/state.md | 2 +- docs/fr/testing.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/fr/state.md b/docs/fr/state.md index 8450eb3d4..3a329d372 100644 --- a/docs/fr/state.md +++ b/docs/fr/state.md @@ -8,7 +8,7 @@ L'arbre d'état unique n'entre pas en conflit avec la modularité. Dans les proc ### Récupération d'état Vuex dans des composants Vue -Alors, comment affichons-nous l'état du store dans nos composants Vue ? Puisque les stores Vuex sont réactifs, la façon la plus simple d'y « récupérer » l'état est tout simplement de retourner une partie de l'état depuis une [une propriété calculée](http://fr.vuejs.org/guide/computed.html) : +Alors, comment affichons-nous l'état du store dans nos composants Vue ? Puisque les stores Vuex sont réactifs, la façon la plus simple d'y « récupérer » l'état est tout simplement de retourner une partie de l'état depuis une [une propriété calculée](https://fr.vuejs.org/guide/computed.html) : ``` js // créons un composant Counter diff --git a/docs/fr/testing.md b/docs/fr/testing.md index b0243f806..16d68f247 100644 --- a/docs/fr/testing.md +++ b/docs/fr/testing.md @@ -219,4 +219,4 @@ mocha test-bundle.js #### Lancer dans un navigateur avec Karma + karma-webpack -Consultez la procédure sur la [documentation vue-loader](http://vue-loader.vuejs.org/en/workflow/testing.html). +Consultez la procédure sur la [documentation vue-loader](https://vue-loader.vuejs.org/en/workflow/testing.html). From 95c33429619405da7d31b3a5db2bdc132f2c230d Mon Sep 17 00:00:00 2001 From: Bruno Lesieur Date: Tue, 26 Sep 2017 07:47:41 +0200 Subject: [PATCH 10/21] September updates Signed-off-by: Bruno Lesieur --- docs/fr/getting-started.md | 2 +- docs/fr/mutations.md | 3 ++- docs/fr/testing.md | 4 ++-- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/docs/fr/getting-started.md b/docs/fr/getting-started.md index cd810a0ac..63437ecd2 100644 --- a/docs/fr/getting-started.md +++ b/docs/fr/getting-started.md @@ -13,7 +13,7 @@ Au cœur de chaque application Vuex, il y a la **zone de stockage (« store »)* Après [avoir installé](installation.md) Vuex, nous allons créer un store. C'est assez simple ; définissez juste un objet d'état initial et quelques mutations : ``` js -// Assurez vous d'appeler `Vue.use(Vuex)` en premier lieu si vous utilisez un système de module +// Assurez vous d'appeler `Vuex.use(Vuex)` en premier lieu si vous utilisez un système de module const store = new Vuex.Store({ state: { diff --git a/docs/fr/mutations.md b/docs/fr/mutations.md index 2aa17a002..ecfa8df70 100644 --- a/docs/fr/mutations.md +++ b/docs/fr/mutations.md @@ -48,6 +48,7 @@ mutations: { } } ``` + ``` js store.commit('increment', { amount: 10 @@ -160,7 +161,7 @@ export default { ### En avant vers les actions -L'asynchronisme combiné à la mutation de l'état peut rendre votre programme très difficile à comprendre. Par exemple, lorsque vous appelez deux méthodes avec toutes les deux des fonctions de rappel asynchrones qui changent l'état, comment savez-vous quelle fonction de rappel est appelée en première ? C'est exactement la raison pour laquelle nous voulons séparer les deux concepts. Avec Vuex, **les mutations sont des transactions synchrones** : +L'asynchronisme combiné à la mutation de l'état peut rendre votre programme très difficile à comprendre. Par exemple, lorsque vous appelez deux méthodes avec toutes les deux des foncitons de rappel asynchrones qui changent l'état, comment savez-vous quelle fonction de rappel est appelée en première ? C'est exactement la raison pour laquelle nous voulons séparer les deux concepts. Avec Vuex, **les mutations sont des transactions synchrones** : ``` js store.commit('increment') diff --git a/docs/fr/testing.md b/docs/fr/testing.md index 16d68f247..120e14556 100644 --- a/docs/fr/testing.md +++ b/docs/fr/testing.md @@ -9,7 +9,7 @@ Les mutations sont très simples à tester, puisque ce sont de simples fonctions ``` js const state = { ... } -// exporter les mutations en tant qu'export nommé +// exporter `mutations` en tant qu'export nommé export const mutations = { ... } export default new Vuex.Store({ @@ -32,7 +32,7 @@ export const mutations = { import { expect } from 'chai' import { mutations } from './store' -// assignement des mutations par déstructuration +// assignement de `mutations` par déstructuration const { increment } = mutations describe('mutations', () => { From b5182c3db812c86335a6fa915208679a622f9516 Mon Sep 17 00:00:00 2001 From: Bruno Lesieur Date: Tue, 26 Sep 2017 07:55:23 +0200 Subject: [PATCH 11/21] Fix small errors Signed-off-by: Bruno Lesieur --- docs/fr/getting-started.md | 2 +- docs/fr/mutations.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/fr/getting-started.md b/docs/fr/getting-started.md index 63437ecd2..cd810a0ac 100644 --- a/docs/fr/getting-started.md +++ b/docs/fr/getting-started.md @@ -13,7 +13,7 @@ Au cœur de chaque application Vuex, il y a la **zone de stockage (« store »)* Après [avoir installé](installation.md) Vuex, nous allons créer un store. C'est assez simple ; définissez juste un objet d'état initial et quelques mutations : ``` js -// Assurez vous d'appeler `Vuex.use(Vuex)` en premier lieu si vous utilisez un système de module +// Assurez vous d'appeler `Vue.use(Vuex)` en premier lieu si vous utilisez un système de module const store = new Vuex.Store({ state: { diff --git a/docs/fr/mutations.md b/docs/fr/mutations.md index ecfa8df70..af330107e 100644 --- a/docs/fr/mutations.md +++ b/docs/fr/mutations.md @@ -161,7 +161,7 @@ export default { ### En avant vers les actions -L'asynchronisme combiné à la mutation de l'état peut rendre votre programme très difficile à comprendre. Par exemple, lorsque vous appelez deux méthodes avec toutes les deux des foncitons de rappel asynchrones qui changent l'état, comment savez-vous quelle fonction de rappel est appelée en première ? C'est exactement la raison pour laquelle nous voulons séparer les deux concepts. Avec Vuex, **les mutations sont des transactions synchrones** : +L'asynchronisme combiné à la mutation de l'état peut rendre votre programme très difficile à comprendre. Par exemple, lorsque vous appelez deux méthodes avec toutes les deux des fonctions de rappel asynchrones qui changent l'état, comment savez-vous quelle fonction de rappel est appelée en première ? C'est exactement la raison pour laquelle nous voulons séparer les deux concepts. Avec Vuex, **les mutations sont des transactions synchrones** : ``` js store.commit('increment') From fb52bae0b180aa57786ccfddc7bb1dc32ea34fc2 Mon Sep 17 00:00:00 2001 From: Bruno Lesieur Date: Mon, 2 Oct 2017 09:21:29 +0200 Subject: [PATCH 12/21] Review de @rspt Signed-off-by: Bruno Lesieur --- docs/fr/actions.md | 4 ++-- docs/fr/api.md | 18 +++++++++--------- docs/fr/getters.md | 2 +- docs/fr/intro.md | 8 ++++---- docs/fr/modules.md | 22 +++++++++++----------- docs/fr/mutations.md | 4 ++-- docs/fr/plugins.md | 4 ++-- docs/fr/state.md | 12 ++++++------ docs/fr/strict.md | 2 +- docs/fr/structure.md | 4 ++-- docs/fr/testing.md | 4 ++-- 11 files changed, 42 insertions(+), 42 deletions(-) diff --git a/docs/fr/actions.md b/docs/fr/actions.md index 8eb68d444..224d638d9 100644 --- a/docs/fr/actions.md +++ b/docs/fr/actions.md @@ -27,7 +27,7 @@ const store = new Vuex.Store({ Les gestionnaires d'action reçoivent un objet contexte qui expose le même ensemble de méthodes et propriétés que l'instance du store, donc vous pouvez appeler `context.commit` pour acter une mutation, ou accéder à l'état et aux accesseurs via `context.state` et `context.getters`. Nous verrons pourquoi cet objet contexte n'est pas l'instance du store elle-même lorsque nous présenterons les [Modules](modules.md) plus tard. -En pratique, nous utilisons souvent la [destructuration d'argument](https://developer.mozilla.org/fr/docs/Web/JavaScript/Reference/Op%C3%A9rateurs/Affecter_par_d%C3%A9composition) pour simplifier quelque peu le code (particulièrement si nous avons besoin d'appeler `commit` plusieurs fois) : +En pratique, nous utilisons souvent la [déstructuration d'argument](https://developer.mozilla.org/fr/docs/Web/JavaScript/Reference/Op%C3%A9rateurs/Affecter_par_d%C3%A9composition) pour simplifier quelque peu le code (particulièrement si nous avons besoin d'appeler `commit` plusieurs fois) : ``` js actions: { @@ -175,4 +175,4 @@ actions: { } ``` -> Il est possible pour un `store.dispatch` de déclencher plusieurs gestionnaires d'action dans différents modules. Dans ce genre de cas, la valeur retournée sera une Promesse qui se résoud quand tous les gestionnaires déclenchés ont été résolus. +> Il est possible pour un `store.dispatch` de déclencher plusieurs gestionnaires d'action dans différents modules. Dans ce genre de cas, la valeur retournée sera une Promesse qui se résout quand tous les gestionnaires déclenchés ont été résolus. diff --git a/docs/fr/api.md b/docs/fr/api.md index 448777db1..5a6e4c16f 100644 --- a/docs/fr/api.md +++ b/docs/fr/api.md @@ -52,7 +52,7 @@ const store = new Vuex.Store({ ...options }) ``` state, // sera l'état local du module si défini dans un module. - getters // indentique à `store.getters` + getters // identique à `store.getters` ``` Arguments spécifiques quand défini dans un module @@ -88,7 +88,7 @@ const store = new Vuex.Store({ ...options }) } ``` - Chaque module peut contenir `state` et `mutations`, tout comme les options racine. L'état d'un module sera attaché à l'état racine du store en utilisant la clé du module. Les mutations et accesseurs d'un module recevront seulement l'état local du module en premier argument au lieu de l'état racine, et le `context.state` des actions du module pointeront également vers l'état local. + Chaque module peut contenir `state` et `mutations`, tout comme les options racines. L'état d'un module sera attaché à l'état racine du store en utilisant la clé du module. Les mutations et accesseurs d'un module recevront seulement l'état local du module en premier argument au lieu de l'état racine, et le `context.state` des actions du module pointeront également vers l'état local. [Plus de détails](modules.md) @@ -96,7 +96,7 @@ const store = new Vuex.Store({ ...options }) - type : `Array` - Un tableau de fonctions plugins qui seront appliquées au store. Un plugin reçoit simplement le store comme seul argument et peut soit écouter les mutations (pour la persistence de données, les logs ou le débogage) ou propager des mutations (pour les données internes, c.-à-d. websockets ou observables). + Un tableau de fonctions plugins qui seront appliquées au store. Un plugin reçoit simplement le store comme seul argument et peut soit écouter les mutations (pour la persistance de données, les logs ou le débogage) ou propager des mutations (pour les données internes, c.-à-d. websockets ou observables). [Plus de détails](plugins.md) @@ -145,7 +145,7 @@ const store = new Vuex.Store({ ...options }) - **`subscribe(handler: Function)`** - S'abonner aux mutations du store. Le `handler` est appelé après chaque mutation et reçoit le descripteur de mutation et l'état post-mutation comme arguments : + S'abonner aux mutations du store. Le `handler` est appelé après chaque mutation et reçoit le descripteur de mutation et l'état post mutation comme arguments : ``` js store.subscribe((mutation, state) => { @@ -172,27 +172,27 @@ const store = new Vuex.Store({ ...options }) - **`mapState(namespace?: string, map: Array | Object): Object`** - Créer des propriétés calculées qui retournent le sous arbre du store Vuex au composant. [Plus de détails](state.md#le-helper-mapstate) + Créer des propriétés calculées qui retournent le sous-arbre du store Vuex au composant. [Plus de détails](state.md#le-helper-mapstate) - Le premier argument peut être de façon optionnel une chaîne d'espace de nom. [Plus de détails](modules.md#Fonctions-utilitaires-liées-avec-espace-de-nom) + Le premier argument peut être de façon optionnelle une chaine d'espace de nom. [Plus de détails](modules.md#Fonctions-utilitaires-liées-avec-espace-de-nom) - **`mapGetters(namespace?: string, map: Array | Object): Object`** Créer des propriétés calculées qui retournent la valeur calculée d'un accesseur. [Plus de détails](getters.md#la-function-utilitaire-mapgetters) - Le premier argument peut être de façon optionnel une chaîne d'espace de nom. [Plus de détails](modules.md#Fonctions-utilitaires-liées-avec-espace-de-nom) + Le premier argument peut être de façon optionnelle une chaine d'espace de nom. [Plus de détails](modules.md#Fonctions-utilitaires-liées-avec-espace-de-nom) - **`mapActions(namespace?: string, map: Array | Object): Object`** Créer des méthodes de composant qui propagent une action. [Plus de détails](actions.md#propager-des-actions-dans-les-composants) - Le premier argument peut être de façon optionnel une chaîne d'espace de nom. [Plus de détails](modules.md#Fonctions-utilitaires-liées-avec-espace-de-nom) + Le premier argument peut être de façon optionnelle une chaine d'espace de nom. [Plus de détails](modules.md#Fonctions-utilitaires-liées-avec-espace-de-nom) - **`mapMutations(namespace?: string, map: Array | Object): Object`** Créer des méthodes de composant qui actent une mutation. [Plus de détails](mutations.md#acter-des-mutations-dans-les-composants) - Le premier argument peut être de façon optionnel une chaîne d'espace de nom. [Plus de détails](modules.md#Fonctions-utilitaires-liées-avec-espace-de-nom) + Le premier argument peut être de façon optionnelle une chaine d'espace de nom. [Plus de détails](modules.md#Fonctions-utilitaires-liées-avec-espace-de-nom) - **`createNamespacedHelpers(namespace: string): Object`** diff --git a/docs/fr/getters.md b/docs/fr/getters.md index 826bac3dc..3df5ea0dc 100644 --- a/docs/fr/getters.md +++ b/docs/fr/getters.md @@ -12,7 +12,7 @@ computed: { Si plus d'un composant a besoin d'utiliser cela, il nous faut ou bien dupliquer cette fonction, ou bien l'extraire dans une fonction utilitaire séparée et l'importer aux endroits nécessaires. Les deux idées sont loin d'être idéales. -Vuex nous permet de définir des accesseurs (« getters ») dans le store. Voyez-les comme les propriétés calculées des stores. Comme pour les propriétés calculées, le résultat de l'accesseur est mis en cache en se basant sur ses dépendances et il ne sera ré-évalué quand l'une de ses dépendances aura changé. +Vuex nous permet de définir des accesseurs (« getters ») dans le store. Voyez-les comme les propriétés calculées des stores. Comme pour les propriétés calculées, le résultat de l'accesseur est mis en cache en se basant sur ses dépendances et il ne sera réévalué quand l'une de ses dépendances aura changé. Les accesseurs prennent l'état en premier argument : diff --git a/docs/fr/intro.md b/docs/fr/intro.md index 34edc7797..81452121c 100644 --- a/docs/fr/intro.md +++ b/docs/fr/intro.md @@ -27,13 +27,13 @@ new Vue({ }) ``` -C'est une application auto-suffisante avec les parties suivantes : +C'est une application autosuffisante avec les parties suivantes : - L'**état**, qui est la source de vérité qui pilotant votre application, - La **vue**, qui est une réflexion déclarative de l'**état**, - Les **actions**, qui sont les façons possibles pour l'état de changer en réaction aux actions utilisateurs depuis la **vue**. -Voici une représentation extrèmement simple du concept de « flux de donnée unidirectionnel » : +Voici une représentation extrêmement simple du concept de « flux de donnée unidirectionnel » :

@@ -56,8 +56,8 @@ Voilà l'idée de base derrière Vuex, inspiré par [Flux](https://facebook.gith ### Quand l'utiliser ? -Bien que Vuex nous aide à gérer un état global partagé, il apporte aussi le coût de nouveaux concepts et _abstraction de code_ (« boilerplate »). C'est un compromis entre la productivité à court terme et à long terme. +Bien que Vuex nous aide à gérer un état global partagé, il apporte aussi le cout de nouveaux concepts et _abstraction de code_ (« boilerplate »). C'est un compromis entre la productivité à court terme et à long terme. -Si vous n'avez jamais créé une _application monopage_ à grande échelle et que vous sautez directement dans Vuex, cela peut paraître verbeux et intimidant. C'est parfaitement normal ; si votre application est simple, vous vous en sortirez sans doute très bien sans Vuex. Un simple [canal d'évènement global](https://fr.vuejs.org/v2/guide/components.html#Communication-non-parent-enfant) pourrait très bien vous suffire. Mais si vous devez créer une application monopage à moyenne ou grande échelle, il y a des chances que vous vous trouviez dans des situations qui vous feront vous interroger sur une meilleure gestion de l'état global, détaché de votre composant Vue, et Vuex sera naturellement la prochaine étape pour vous. Voici une bonne citation de Dan Abramov, l'auteur de Redux : +Si vous n'avez jamais créé une _application monopage_ à grande échelle et que vous sautez directement dans Vuex, cela peut paraitre verbeux et intimidant. C'est parfaitement normal ; si votre application est simple, vous vous en sortirez sans doute très bien sans Vuex. Un simple [canal d'évènement global](https://fr.vuejs.org/v2/guide/components.html#Communication-non-parent-enfant) pourrait très bien vous suffire. Mais si vous devez créer une application monopage à moyenne ou grande échelle, il y a des chances que vous vous trouviez dans des situations qui vous feront vous interroger sur une meilleure gestion de l'état global, détaché de votre composant Vue, et Vuex sera naturellement la prochaine étape pour vous. Voici une bonne citation de Dan Abramov, l'auteur de Redux : > « Les librairies Flux, c'est comme les lunettes : vous saurez quand vous en aurez besoin. » diff --git a/docs/fr/modules.md b/docs/fr/modules.md index 4f16913a8..4d86649cf 100644 --- a/docs/fr/modules.md +++ b/docs/fr/modules.md @@ -2,7 +2,7 @@ Du fait de l'utilisation d'un arbre d'état unique, tout l'état de notre application est contenu dans un seul et même gros objet. Cependant, au fur et à mesure que notre application grandit, le store peut devenir très engorgé. -Pour y remédier, Vuex nous permet de diviser notre store en **modules**. Chaque module peut contenir ses propres état, mutations, actions, accesseurs. Il peut même contenir ses propres modules internes. +Pour y remédier, Vuex nous permet de diviser notre store en **modules**. Chaque module peut contenir ses propres états, mutations, actions, accesseurs. Il peut même contenir ses propres modules internes. ``` js const moduleA = { @@ -83,7 +83,7 @@ const moduleA = { Par défaut, les actions, mutations et accesseurs à l'intérieur d'un module sont toujours enregistrés sous l'**espace de nom global**. Cela permet à de multiples modules d'être réactifs au même type de mutation et d'action. -Si vous souhaitez que votre module soit auto-suffisant et réutilisable, vous pouvez le ranger sous un espace de nom avec `namespaced: true`. Quand le module est enregistré, tous ses accesseurs, actions et mutations seront automatiquement basés sur l'espace de nom du module dans lesquels ils sont rangés. Par exemple : +Si vous souhaitez que votre module soit autosuffisant et réutilisable, vous pouvez le ranger sous un espace de nom avec `namespaced: true`. Quand le module est enregistré, tous ses accesseurs, actions et mutations seront automatiquement basés sur l'espace de nom du module dans lesquels ils sont rangés. Par exemple : ```js const store = new Vuex.Store({ @@ -128,13 +128,13 @@ const store = new Vuex.Store({ }) ``` -Les accesseurs et actions sous espace de nom reçoivent des `getters`, `dispatch` et `commit` localisés. En d'autres termes, vous pouvez utiliser les paramètres de module sans écrire de prefix dans ce même module. Permuter entre un espace de nom ou non n'affecte pas le code à l'intérieur du module. +Les accesseurs et actions sous espace de nom reçoivent des `getters`, `dispatch` et `commit` localisés. En d'autres termes, vous pouvez utiliser les paramètres de module sans écrire de préfixe dans ce même module. Permuter entre un espace de nom ou non n'affecte pas le code à l'intérieur du module. #### Accéder aux propriétés globales dans les modules à espace de nom -Si vous voulez utiliser des états et accesseurs globaux, `rootState` et `rootGetters` sont passés en 3ième et 4ième arguments des fonctions d'accès et sont également exposés en tant que propriété de l'objet `context` passé aux fonctions d'action. +Si vous voulez utiliser des états et accesseurs globaux, `rootState` et `rootGetters` sont passés en 3ᵉ et 4ᵉ arguments des fonctions d'accès et sont également exposés en tant que propriété de l'objet `context` passé aux fonctions d'action. -Pour propager les actions ou les mutations actées dans l'espace de nom global, passez `{ root: true }` en 3ième argument à `dispatch` et `commit`. +Pour propager les actions ou les mutations actées dans l'espace de nom global, passez `{ root: true }` en 3ᵉ argument à `dispatch` et `commit`. ``` js modules: { @@ -143,7 +143,7 @@ modules: { getters: { // Les `getters` sont localisés dans le module des accesseurs - // vous pouvez utiliser `rootGetters` via le 4ième argument des accesseurs + // vous pouvez utiliser `rootGetters` via le 4ᵉ argument des accesseurs someGetter (state, getters, rootState, rootGetters) { getters.someOtherGetter // -> 'foo/someOtherGetter' rootGetters.someOtherGetter // -> 'someOtherGetter' @@ -189,7 +189,7 @@ methods: { } ``` -Dans ces cas là, vous pouvez passer une chaîne de caractère représentant le nom d'espace en tant que premier argument aux fonctions utilitaires ainsi toutes les liaisons seront faites en utilisant le module comme contexte. Cela peut être simplifié comme ci-dessous : +Dans ces cas-là, vous pouvez passer une chaine de caractère représentant le nom d'espace en tant que premier argument aux fonctions utilitaires ainsi toutes les liaisons seront faites en utilisant le module comme contexte. Cela peut être simplifié comme ci-dessous : ``` js computed: { @@ -206,7 +206,7 @@ methods: { } ``` -De plus, vous pouvez créer des fonctions utilitaires liées avec espace de nom en utilisant `createNamespacedHelpers`. Cela retourne un objet qui a les nouvelles fonctions utilitaires ratachées à la valeur d'espace de nom fournie : +De plus, vous pouvez créer des fonctions utilitaires liées avec espace de nom en utilisant `createNamespacedHelpers`. Cela retourne un objet qui a les nouvelles fonctions utilitaires rattachées à la valeur d'espace de nom fournie : ``` js import { createNamespacedHelpers } from 'vuex' @@ -233,7 +233,7 @@ export default { #### Limitations pour les plugins des développeurs -Vous devez faire attention au nom d'espace imprévisible pour vos modules quand vous créez un [plugin](plugins.md) qui fournit les modules et laisser les utilisateurs les ajouter au store de Vuex. Vos modules seront également sous espace de nom si l'utilisateur du plugin l'ajoute sous un module sous espace de nom. Pour vous adaptez à la situation, vous devez recevoir la valeur de l'espace de nom via vos options de plugin : +Vous devez faire attention au nom d'espace imprévisible pour vos modules quand vous créez un [plugin](plugins.md) qui fournit les modules et laisser les utilisateurs les ajouter au store de Vuex. Vos modules seront également sous espace de nom si l'utilisateur du plugin l'ajoute sous un module sous espace de nom. Pour vous adapter à la situation, vous devez recevoir la valeur de l'espace de nom via vos options de plugin : ```js // passer la valeur d'espace de nom via une option du plugin @@ -269,7 +269,7 @@ L'enregistrement dynamique de module permet aux autres plugins Vue de bénéfici Vous pouvez aussi supprimer un module enregistré dynamiquement avec `store.unregisterModule(moduleName)`. Notez que vous ne pouvez pas supprimer des modules statiques (déclarés à la création du store) avec cette méthode. -### Ré-utiliser un module +### Réutiliser un module Parfois nous devrons créer de multiples instances d'un module pour, par exemple : @@ -289,4 +289,4 @@ const MyReusableModule = { }, // mutations, actions, accesseurs... } -``` \ No newline at end of file +``` diff --git a/docs/fr/mutations.md b/docs/fr/mutations.md index af330107e..3b867d250 100644 --- a/docs/fr/mutations.md +++ b/docs/fr/mutations.md @@ -1,6 +1,6 @@ # Mutations -La seule façon de vraiment modifier l'état dans un store Vuex est d'acter une mutation. Les mutations Vuex sont très similaires aux évènements : chaque mutation a un **type** sous forme de chaîne de caractères et un **gestionnaire**. La fonction de gestion est en charge de procéder aux véritables modifications de l'état, et elle reçoit l'état en premier argument : +La seule façon de vraiment modifier l'état dans un store Vuex est d'acter une mutation. Les mutations Vuex sont très similaires aux évènements : chaque mutation a un **type** sous forme de chaine de caractères et un **gestionnaire**. La fonction de gestion est en charge de procéder aux véritables modifications de l'état, et elle reçoit l'état en premier argument : ``` js const store = new Vuex.Store({ @@ -134,7 +134,7 @@ mutations: { } ``` -Maintenant imaginons que nous deboguons l'application et que nous regardons dans les logs de mutation des outils de développement (« devtools »). Pour chaque mutation enregistrée, le devtool aura besoin de capturer un instantané de l'état « avant » et un instantané « après ». Cependant, la fonction de rappel asynchrone de l'exemple ci-dessus rend l'opération impossible : la fonction de rappel n'est pas encore appelée lorsque la mutation est actée, et il n'y a aucun moyen pour le devtool de savoir quand la fonction de rappel sera véritablement appelée. Toute mutation d'état effectuée dans la fonction de rappel est essentiellement intraçable ! +Maintenant imaginons que nous déboguons l'application et que nous regardons dans les logs de mutation des outils de développement (« devtools »). Pour chaque mutation enregistrée, le devtool aura besoin de capturer un instantané de l'état « avant » et un instantané « après ». Cependant, la fonction de rappel asynchrone de l'exemple ci-dessus rend l'opération impossible : la fonction de rappel n'est pas encore appelée lorsque la mutation est actée, et il n'y a aucun moyen pour le devtool de savoir quand la fonction de rappel sera véritablement appelée. Toute mutation d'état effectuée dans la fonction de rappel est essentiellement intraçable ! ### Acter des mutations dans les composants diff --git a/docs/fr/plugins.md b/docs/fr/plugins.md index 0daf01a78..20d13c972 100644 --- a/docs/fr/plugins.md +++ b/docs/fr/plugins.md @@ -7,7 +7,7 @@ const myPlugin = store => { // appelé quand le store est initialisé store.subscribe((mutation, state) => { // appelé après chaque mutation. - // Les mutation arrivent au format `{ type, payload }`. + // Les mutations arrivent au format `{ type, payload }`. }) } ``` @@ -54,7 +54,7 @@ const store = new Vuex.Store({ ### Prendre des instantanés de l'état -Parfois un plugin peut vouloir recevoir des « instantanés » de l'état, et également comparer l'état post-mutation avec l'état pré-mutation. Pour faire ceci, vous aurez besoin d'effectuer une copie complète de l'état : +Parfois un plugin peut vouloir recevoir des « instantanés » de l'état, et également comparer l'état post mutation avec l'état prémutation. Pour faire ceci, vous aurez besoin d'effectuer une copie complète de l'état : ``` js const myPluginWithSnapshot = store => { diff --git a/docs/fr/state.md b/docs/fr/state.md index 3a329d372..2436a157b 100644 --- a/docs/fr/state.md +++ b/docs/fr/state.md @@ -22,11 +22,11 @@ const Counter = { } ``` -Lorsque `store.state.count` change, cela entraînera la ré-évaluation de la propriété calculée, et déclenchera les actions associées au DOM. +Lorsque `store.state.count` change, cela entrainera la réévaluation de la propriété calculée, et déclenchera les actions associées au DOM. Cependant, ce modèle oblige le composant à compter sur le singleton global du store. Lorsqu'on utilise un système de module, il est nécessaire d'importer le store dans tous les composants qui utilisent l'état du store, et il est également nécessaire de le simuler lorsque l'on teste le composant. -Vuex fournit un méchanisme pour « injecter » le store dans tous les composants enfants du composant racine avec l'option `store` (activée par `Vue.use(Vuex)`) : +Vuex fournit un mécanisme pour « injecter » le store dans tous les composants enfants du composant racine avec l'option `store` (activée par `Vue.use(Vuex)`) : ``` js const app = new Vue({ @@ -58,10 +58,10 @@ const Counter = { ### La fonction utilitaire `mapState` -Lorsqu'un composant a besoin d'utiliser plusieurs accesseurs ou propriétés de l'état du store, déclarer toutes ces propriétés calculées peut devenir répétitif et verbeux. Afin de palier à ça, nous pouvons utiliser la fonction utilitaire `mapState` qui génère des fonctions d'accession pour nous et nous épargne quelques coups de clavier : +Lorsqu'un composant a besoin d'utiliser plusieurs accesseurs ou propriétés de l'état du store, déclarer toutes ces propriétés calculées peut devenir répétitif et verbeux. Afin de pallier à ça, nous pouvons utiliser la fonction utilitaire `mapState` qui génère des fonctions d'accession pour nous et nous épargne quelques coups de clavier : ``` js -// dans la version complète, des fonctions utilitaires sont exposées tel que `Vuex.mapState` +// dans la version complète, des fonctions utilitaires sont exposées telles que `Vuex.mapState` import { mapState } from 'vuex' export default { @@ -81,7 +81,7 @@ export default { } ``` -Il est également possible de fournir un tableau de chaînes de caractères à `mapState` lorsque le nom de la propriété de l'état du store est le même que celui du composant. +Il est également possible de fournir un tableau de chaines de caractères à `mapState` lorsque le nom de la propriété de l'état du store est le même que celui du composant. ``` js computed: mapState([ @@ -106,4 +106,4 @@ computed: { ### Les composants peuvent toujours avoir un état local -Utiliser Vuex ne signifie pas que vous devez mettre **tout** votre état dans Vuex. Bien que le fait de mettre plus d'état dans Vuex rende vos mutation d'état plus explicites et plus débogable, parfois il peut aussi rendre le code plus verbeux et indirect. Si une partie de l'état appartient directement à un seul composant, il est parfaitement sain de la laisser dans l'état local. Assurez vous de prendre en compte les avantages et inconvénients d'une telle décision afin de vous adapter au mieux aux besoins de votre application. +Utiliser Vuex ne signifie pas que vous devez mettre **tout** votre état dans Vuex. Bien que le fait de mettre plus d'états dans Vuex rende vos mutations d'état plus explicites et plus débogable, parfois il peut aussi rendre le code plus verbeux et indirect. Si une partie de l'état appartient directement à un seul composant, il est parfaitement sain de la laisser dans l'état local. Assurez-vous de prendre en compte les avantages et inconvénients d'une telle décision afin de vous adapter au mieux aux besoins de votre application. diff --git a/docs/fr/strict.md b/docs/fr/strict.md index a2720648d..eb92a494d 100644 --- a/docs/fr/strict.md +++ b/docs/fr/strict.md @@ -13,7 +13,7 @@ En mode strict, lorsque l'état de Vuex est modifié en dehors des gestionnaires ### Développement vs. production -**N'activez pas le mode strict lorsque vous déployez en production !** Le mode strict lance une observation récursive de l'arbre d'état pour détecter des mutations inappropriées. Assurrez-vous de l'avoir désactivé en production pour éviter un coût sur les performances. +**N'activez pas le mode strict lorsque vous déployez en production !** Le mode strict lance une observation récursive de l'arbre d'état pour détecter des mutations inappropriées. Assurez-vous de l'avoir désactivé en production pour éviter un cout sur les performances. Tout comme les plugins, nous pouvons laisser nos outils de build gérer ça : diff --git a/docs/fr/structure.md b/docs/fr/structure.md index 3469b301e..691bd3f62 100644 --- a/docs/fr/structure.md +++ b/docs/fr/structure.md @@ -10,7 +10,7 @@ Vuex ne vous restreint pas quand à la structure de code à utiliser. Il impose Tant que vous suivez ces règles, c'est à vous de structurer votre projet. Si votre fichier de store devient trop gros, commencez dès lors à séparer les actions, mutations et accesseurs dans des fichiers séparés. -Pour une application non-triviale, nous aurons probablement besoin de faire appel à des modules. Voici un exemple de structure de projet : +Pour une application non triviale, nous aurons probablement besoin de faire appel à des modules. Voici un exemple de structure de projet : ``` bash ├── index.html @@ -29,4 +29,4 @@ Pour une application non-triviale, nous aurons probablement besoin de faire appe    └── products.js # module de produit ``` -Vous pouvez jeter à un œil à l'[exemple de panier d'achat](https://github.com/vuejs/vuex/tree/dev/examples/shopping-cart). +Vous pouvez jeter à un œil à l'[exemple de panier d'achats](https://github.com/vuejs/vuex/tree/dev/examples/shopping-cart). diff --git a/docs/fr/testing.md b/docs/fr/testing.md index 120e14556..552dc8553 100644 --- a/docs/fr/testing.md +++ b/docs/fr/testing.md @@ -111,7 +111,7 @@ const testAction = (action, args, state, expectedMutations, done) => { // appeler l'action avec le store simulé et les arguments action({ commit, state }, ...args) - // vérifier qu'aucune mutations n'ai été propagée + // vérifier qu'aucune mutation n'ait été propagée if (expectedMutations.length === 0) { expect(count).to.equal(0) done() @@ -163,7 +163,7 @@ describe('getters', () => { // accesseur simulé const filterCategory = 'fruit' - // obterir le résultat depuis l'accesseur + // obtenir le résultat depuis l'accesseur const result = getters.filteredProducts(state, { filterCategory }) // tester le résultat From 3cb544b32f2ba479bfb105561be3a59ca03f9498 Mon Sep 17 00:00:00 2001 From: Bruno Lesieur Date: Sat, 21 Oct 2017 17:19:03 +0200 Subject: [PATCH 13/21] New translation for v2.5 Signed-off-by: Bruno Lesieur --- docs/fr/SUMMARY.md | 5 +---- docs/fr/api.md | 26 ++++++++++++++++++++++---- docs/fr/modules.md | 2 ++ docs/fr/plugins.md | 3 ++- 4 files changed, 27 insertions(+), 9 deletions(-) diff --git a/docs/fr/SUMMARY.md b/docs/fr/SUMMARY.md index ac0cb53a8..975230d8f 100644 --- a/docs/fr/SUMMARY.md +++ b/docs/fr/SUMMARY.md @@ -1,10 +1,7 @@ # Vuex - -> Note : Ceci est la documentation pour vuex@2.x. - +> Note aux utilisateurs de TypeScript : vuex@3.0+ nécessite vue@>2.5+, et inverssement. -- [Vous cherchez la documentation de la v1.0 ?](https://github.com/vuejs/vuex/tree/1.0/docs) - [Notes de version](https://github.com/vuejs/vuex/releases) - [Installation](installation.md) - [Vuex, qu'est-ce que c'est ?](intro.md) diff --git a/docs/fr/api.md b/docs/fr/api.md index 5a6e4c16f..f3d443906 100644 --- a/docs/fr/api.md +++ b/docs/fr/api.md @@ -12,11 +12,11 @@ const store = new Vuex.Store({ ...options }) - **state** - - type : `Object` + - type : `Object | Function` - L'objet d'état racine pour le store Vuex. + L'objet d'état racine pour le store Vuex. [Plus de détails](state.md) - [Plus de détails](state.md) + Si vous passez une fonction qui retourne un objet, l'objet retourné est utilisé en tant qu'état racine. Ceci est utile quand vous voulez réutiliser un objet d'état surtout dans un cas de réutilisation de module. [Plus de détails](modules.md#réutiliser-un-module) - **mutations** @@ -39,6 +39,7 @@ const store = new Vuex.Store({ ...options }) commit, // identique à `store.commit` dispatch, // identique à `store.dispatch` getters // identique à `store.getters` + rootGetters // identique à `store.getters`, seulement dans les modules } ``` @@ -156,10 +157,27 @@ const store = new Vuex.Store({ ...options }) Utilisé plus communément dans les plugins. [Plus de détails](plugins.md) -- **`registerModule(path: string | Array, module: Module)`** +- **`subscribeAction(handler: Function)`** + + > Nouveau dans la 2.5.0+ + + S'abonner au actions du store. Le `handler` est appelé pour chaque action propagée et reçoit chaque description d'action et l'état du store courant en arguments : + + ``` js + store.subscribeAction((action, state) => { + console.log(action.type) + console.log(action.payload) + }) + ``` + + Souvent utiliser dans les plugins. [Pour plus de détails](plugins.md) + +- **`registerModule(path: string | Array, module: Module, options?: Object)`** Enregistrer un module dynamique. [Plus de détails](modules.md#enregistrement-dynamique-de-module) + `options` peut avoir `preserveState: true` qui lui permet de préserver l'état précédent. Utile pour du rendu côté serveur. + - **`unregisterModule(path: string | Array)`** Supprimer un module dynamique. [Plus de détails](modules.md#enregistrement-dynamique-de-module) diff --git a/docs/fr/modules.md b/docs/fr/modules.md index 4d86649cf..74b3451b8 100644 --- a/docs/fr/modules.md +++ b/docs/fr/modules.md @@ -269,6 +269,8 @@ L'enregistrement dynamique de module permet aux autres plugins Vue de bénéfici Vous pouvez aussi supprimer un module enregistré dynamiquement avec `store.unregisterModule(moduleName)`. Notez que vous ne pouvez pas supprimer des modules statiques (déclarés à la création du store) avec cette méthode. +Il est possible que vous souhaitiez préserver un état précédent quand vous abonnez un nouveau module. Par exemple préserver l'état depuis l'application rendue côté serveur. Vous pouvez réaliser ceci avec l'option `preserveState` : `store.registerModule('a', module, { preserveState: true })`. + ### Réutiliser un module Parfois nous devrons créer de multiples instances d'un module pour, par exemple : diff --git a/docs/fr/plugins.md b/docs/fr/plugins.md index 20d13c972..8f4316c74 100644 --- a/docs/fr/plugins.md +++ b/docs/fr/plugins.md @@ -116,7 +116,8 @@ const logger = createLogger({ // les mutations sont logguées au format `{ type, payload }` // nous pouvons les formater comme nous le souhaitons. return mutation.type - } + }, + logger: console, // implementation de l'API `console`, par défaut `console` }) ``` From 4d0a1b4190680df40960a893772708cc734c2b75 Mon Sep 17 00:00:00 2001 From: Bruno Lesieur Date: Sat, 21 Oct 2017 17:23:37 +0200 Subject: [PATCH 14/21] API fixes Signed-off-by: Bruno Lesieur --- docs/fr/api.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/fr/api.md b/docs/fr/api.md index f3d443906..e45c6a8e8 100644 --- a/docs/fr/api.md +++ b/docs/fr/api.md @@ -34,11 +34,11 @@ const store = new Vuex.Store({ ...options }) ``` js { - state, // identique à `store.state`, ou à l'état local si dans des modules - rootState, // identique à `store.state`, seulement dans des modules - commit, // identique à `store.commit` - dispatch, // identique à `store.dispatch` - getters // identique à `store.getters` + state, // identique à `store.state`, ou à l'état local si dans des modules + rootState, // identique à `store.state`, seulement dans des modules + commit, // identique à `store.commit` + dispatch, // identique à `store.dispatch` + getters, // identique à `store.getters` rootGetters // identique à `store.getters`, seulement dans les modules } ``` From e7083e184176f298fc5843f30080ccbec02e447f Mon Sep 17 00:00:00 2001 From: Bruno Lesieur Date: Sat, 21 Oct 2017 17:25:44 +0200 Subject: [PATCH 15/21] Re-add title Signed-off-by: Bruno Lesieur --- docs/fr/modules.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/fr/modules.md b/docs/fr/modules.md index 3334f6eb0..74b3451b8 100644 --- a/docs/fr/modules.md +++ b/docs/fr/modules.md @@ -271,6 +271,8 @@ Vous pouvez aussi supprimer un module enregistré dynamiquement avec `store.unre Il est possible que vous souhaitiez préserver un état précédent quand vous abonnez un nouveau module. Par exemple préserver l'état depuis l'application rendue côté serveur. Vous pouvez réaliser ceci avec l'option `preserveState` : `store.registerModule('a', module, { preserveState: true })`. +### Réutiliser un module + Parfois nous devrons créer de multiples instances d'un module pour, par exemple : - créer plusieurs stores qui utilisent le même module (par ex. pour [éviter les singletons d'état avec du SSR](https://ssr.vuejs.org/fr/structure.html#avoid-stateful-singletons) quand l'option `runInNewContext` est à `false` ou `'once'`) ou From 798fd9865f91d9b1800e720ba60a9b6782a0a04d Mon Sep 17 00:00:00 2001 From: Bruno Lesieur Date: Mon, 23 Oct 2017 17:06:34 +0200 Subject: [PATCH 16/21] Official Vue way to speak about a version and more greater version Signed-off-by: Bruno Lesieur --- docs/en/SUMMARY.md | 2 +- docs/fr/SUMMARY.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/en/SUMMARY.md b/docs/en/SUMMARY.md index d1ceafc70..ce35718c0 100644 --- a/docs/en/SUMMARY.md +++ b/docs/en/SUMMARY.md @@ -1,6 +1,6 @@ # Vuex -> Note: for TypeScript users, vuex@>= 3.0 requires vue@>=2.5, and vice versa. +> Note: for TypeScript users, vuex@3.0+ requires vue@2.5+, and vice versa. - [Release Notes](https://github.com/vuejs/vuex/releases) - [Installation](installation.md) diff --git a/docs/fr/SUMMARY.md b/docs/fr/SUMMARY.md index 975230d8f..c15b351c5 100644 --- a/docs/fr/SUMMARY.md +++ b/docs/fr/SUMMARY.md @@ -1,6 +1,6 @@ # Vuex -> Note aux utilisateurs de TypeScript : vuex@3.0+ nécessite vue@>2.5+, et inverssement. +> Note aux utilisateurs de TypeScript : vuex@3.0+ nécessite vue@2.5+, et inverssement. - [Notes de version](https://github.com/vuejs/vuex/releases) - [Installation](installation.md) From 5257511ee1909bf388a9fb538abef953f6c56304 Mon Sep 17 00:00:00 2001 From: Bruno Lesieur Date: Thu, 9 Nov 2017 14:56:54 +0100 Subject: [PATCH 17/21] Last changes for Vuex documentation Signed-off-by: Bruno Lesieur --- docs/fr/SUMMARY.md | 2 +- docs/fr/actions.md | 6 +++--- docs/fr/api.md | 4 ++-- docs/fr/getters.md | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/docs/fr/SUMMARY.md b/docs/fr/SUMMARY.md index c15b351c5..70f298a80 100644 --- a/docs/fr/SUMMARY.md +++ b/docs/fr/SUMMARY.md @@ -1,6 +1,6 @@ # Vuex -> Note aux utilisateurs de TypeScript : vuex@3.0+ nécessite vue@2.5+, et inverssement. +> Note aux utilisateurs de TypeScript : vuex@3.0+ nécessite vue@2.5+, et inversement. - [Notes de version](https://github.com/vuejs/vuex/releases) - [Installation](installation.md) diff --git a/docs/fr/actions.md b/docs/fr/actions.md index dda27e5fc..c5990e97b 100644 --- a/docs/fr/actions.md +++ b/docs/fr/actions.md @@ -37,7 +37,7 @@ actions: { } ``` -### Propager des actions +### Propager des actions dans les composants Les actions sont déclenchées par la méthode `store.dispatch` : @@ -45,7 +45,7 @@ Les actions sont déclenchées par la méthode `store.dispatch` : store.dispatch('increment') ``` -Cela peut sembler idiot au premier abord : si nous avons besoin d'incrémenter le compteur, pourquoi ne pas simplement appeler `store.commit('increment')` directement ? Et bien, vous rappelez-vous que **les mutations doivent être synchrones** ? Les actions ne suivent pas cette règle. Il est possible de procéder à des opérations **asynchrones** dans une action : +Cela peut sembler idiot au premier abord : si nous avons besoin d'incrémenter le compteur, pourquoi ne pas simplement appeler `store.commit('increment')` directement ? Rappelez-vous que **les mutations doivent être synchrones** ? Les actions ne suivent pas cette règle. Il est possible de procéder à des opérations **asynchrones** dans une action : ``` js actions: { @@ -159,7 +159,7 @@ actions: { } ``` -Pour finir, nous pouvons utiliser de [async / await](https://tc39.github.io/ecmascript-asyncawait/), une fonctionnalité JavaScript qui sera disponible très bientôt, nous pouvons composer nos actions ainsi : +Pour finir, si nous utilisons [`async` / `await`](https://tc39.github.io/ecmascript-asyncawait/), nous pouvons composer nos actions ainsi : ``` js // sachant que `getData()` et `getOtherData()` retournent des Promesses. diff --git a/docs/fr/api.md b/docs/fr/api.md index e45c6a8e8..e98bcbaa9 100644 --- a/docs/fr/api.md +++ b/docs/fr/api.md @@ -38,7 +38,7 @@ const store = new Vuex.Store({ ...options }) rootState, // identique à `store.state`, seulement dans des modules commit, // identique à `store.commit` dispatch, // identique à `store.dispatch` - getters, // identique à `store.getters` + getters, // identique à `store.getters`, ou les accesseurs locaux dans les modules rootGetters // identique à `store.getters`, seulement dans les modules } ``` @@ -140,7 +140,7 @@ const store = new Vuex.Store({ ...options }) - **`watch(getter: Function, cb: Function, options?: Object)`** - Observer de façon réactive la valeur de retour d'une fonction accesseur, et appeler la fonction de rappel lorsque la valeur change. L'accesseur reçoit l'état du store comme unique argument. Accepte un objet optionnel d'options qui prend les mêmes options que la méthode `vm.$watch` de Vue. + Observer de façon réactive la valeur de retour d'une fonction accesseur, et appeler la fonction de rappel lorsque la valeur change. L'accesseur reçoit l'état du store en premier argument, et les accesseurs en second argument. Accepte un objet optionnel d'options qui prend les mêmes options que la méthode `vm.$watch` de Vue. Pour arrêter d'observer, appeler la fonction gestionnaire retournée. diff --git a/docs/fr/getters.md b/docs/fr/getters.md index f5e42bef1..70a14ff8d 100644 --- a/docs/fr/getters.md +++ b/docs/fr/getters.md @@ -12,7 +12,7 @@ computed: { Si plus d'un composant a besoin d'utiliser cela, il nous faut ou bien dupliquer cette fonction, ou bien l'extraire dans une fonction utilitaire séparée et l'importer aux endroits nécessaires. Les deux idées sont loin d'être idéales. -Vuex nous permet de définir des accesseurs (« getters ») dans le store. Voyez-les comme les propriétés calculées des stores. Comme pour les propriétés calculées, le résultat de l'accesseur est mis en cache en se basant sur ses dépendances et il ne sera réévalué que lorsqu'une de ses dépendances aura changé. +Vuex nous permet de définir des accesseurs (« getters ») dans le store. Voyez-les comme les propriétés calculées des stores. Comme pour les propriétés calculées, le résultat de l'accesseur est mis en cache en se basant sur ses dépendances et il ne sera réévalué quand l'une de ses dépendances aura changé. Les accesseurs prennent l'état en premier argument : @@ -68,7 +68,7 @@ Vous pouvez aussi passer des arguments aux accesseurs en retournant une fonction ```js getters: { // ... - getTodoById: (state, getters) => (id) => { + getTodoById: (state) => (id) => { return state.todos.find(todo => todo.id === id) } } From d46ccfdd00ec16c891feb28a562cfddc8afa4d6a Mon Sep 17 00:00:00 2001 From: Bruno Lesieur Date: Thu, 9 Nov 2017 15:04:58 +0100 Subject: [PATCH 18/21] Remove extra text Signed-off-by: Bruno Lesieur --- docs/fr/actions.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/fr/actions.md b/docs/fr/actions.md index c5990e97b..cd9512c2b 100644 --- a/docs/fr/actions.md +++ b/docs/fr/actions.md @@ -37,7 +37,7 @@ actions: { } ``` -### Propager des actions dans les composants +### Propager des actions Les actions sont déclenchées par la méthode `store.dispatch` : @@ -45,7 +45,7 @@ Les actions sont déclenchées par la méthode `store.dispatch` : store.dispatch('increment') ``` -Cela peut sembler idiot au premier abord : si nous avons besoin d'incrémenter le compteur, pourquoi ne pas simplement appeler `store.commit('increment')` directement ? Rappelez-vous que **les mutations doivent être synchrones** ? Les actions ne suivent pas cette règle. Il est possible de procéder à des opérations **asynchrones** dans une action : +Cela peut sembler idiot au premier abord : si nous avons besoin d'incrémenter le compteur, pourquoi ne pas simplement appeler `store.commit('increment')` directement ? Vous rappelez-vous que **les mutations doivent être synchrones** ? Les actions ne suivent pas cette règle. Il est possible de procéder à des opérations **asynchrones** dans une action : ``` js actions: { From 1fcf3bb0faba91903343e4ab04cd21105d6df019 Mon Sep 17 00:00:00 2001 From: Bruno Lesieur Date: Thu, 9 Nov 2017 15:10:32 +0100 Subject: [PATCH 19/21] fix typo Signed-off-by: Bruno Lesieur --- docs/fr/getters.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/fr/getters.md b/docs/fr/getters.md index 70a14ff8d..4ed308d36 100644 --- a/docs/fr/getters.md +++ b/docs/fr/getters.md @@ -12,7 +12,7 @@ computed: { Si plus d'un composant a besoin d'utiliser cela, il nous faut ou bien dupliquer cette fonction, ou bien l'extraire dans une fonction utilitaire séparée et l'importer aux endroits nécessaires. Les deux idées sont loin d'être idéales. -Vuex nous permet de définir des accesseurs (« getters ») dans le store. Voyez-les comme les propriétés calculées des stores. Comme pour les propriétés calculées, le résultat de l'accesseur est mis en cache en se basant sur ses dépendances et il ne sera réévalué quand l'une de ses dépendances aura changé. +Vuex nous permet de définir des accesseurs (« getters ») dans le store. Voyez-les comme les propriétés calculées des stores. Comme pour les propriétés calculées, le résultat de l'accesseur est mis en cache en se basant sur ses dépendances et il ne sera réévalué que lorsque l'une de ses dépendances aura changée. Les accesseurs prennent l'état en premier argument : From 67da3211d5d8871f7f7816eeacd0e8e40cce4f92 Mon Sep 17 00:00:00 2001 From: MachinisteWeb Date: Tue, 2 Jan 2018 13:54:08 +0100 Subject: [PATCH 20/21] Update french version Signed-off-by: MachinisteWeb --- docs/fr/state.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/fr/state.md b/docs/fr/state.md index 2436a157b..bec90b519 100644 --- a/docs/fr/state.md +++ b/docs/fr/state.md @@ -81,7 +81,7 @@ export default { } ``` -Il est également possible de fournir un tableau de chaines de caractères à `mapState` lorsque le nom de la propriété de l'état du store est le même que celui du composant. +Il est également possible de fournir un tableau de chaines de caractères à `mapState` lorsque le nom de la propriété calculée de l'état du store est le même que celui du nom du sous élément de l'état. ``` js computed: mapState([ From 20183a8e614e4f74095fb0e3f1a0afe23e2f6ad0 Mon Sep 17 00:00:00 2001 From: MachinisteWeb Date: Tue, 2 Jan 2018 13:58:54 +0100 Subject: [PATCH 21/21] Better translation Signed-off-by: MachinisteWeb --- docs/fr/state.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/fr/state.md b/docs/fr/state.md index bec90b519..34c4a5580 100644 --- a/docs/fr/state.md +++ b/docs/fr/state.md @@ -81,7 +81,7 @@ export default { } ``` -Il est également possible de fournir un tableau de chaines de caractères à `mapState` lorsque le nom de la propriété calculée de l'état du store est le même que celui du nom du sous élément de l'état. +Il est également possible de fournir un tableau de chaines de caractères à `mapState` lorsque le nom de la propriété calculée associée est le même que le nom de l'état du store. ``` js computed: mapState([