From 48263f8c81c73583f42d82b3a9a2c9cad56026fb Mon Sep 17 00:00:00 2001 From: Alexander Sokolov Date: Fri, 18 Jan 2019 11:42:23 +0300 Subject: [PATCH 01/29] docs: [RU] Translation update (#1488) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * structure.md исправлена опечатка * actions.md мелкие правки * api.md мелкие правки * intro.md мелкие правки * state.md мелкие правки * strict.md мелкие правки * testing.md мелкие правки * actions.md правки * testing.md правки * Fix typos. ru * SUMMARY.md правки заголовков * Минусы на тире * [RU] Moved to VuePress * Fix & single quotes * [RU] Update * Remove settings.json * fix link * fix images links * translated ru image and ai sources * Localized images * README.md исправлена ссылка * api: formatting example * api: fix links * docs: remove core-concepts.md * modules.md правка примеров * docs: [RU] fix links anchors * docs: (ru) plugins.md fix * api.md добавлен devtools * api.md добавлена ссылка * api.md обновление * installation.md обновление * README.md обновление * getting-started.md удален, дубль * README.md обновление * installation.md изменена ссылка * README.md правка * state.md обновление * state.md правки * getters.md правки * README.md fix * state.md fix * state.md правки * hot-reload.md правка * mutations.md правка * README.md add video-preview component * api/README.md added about subscribeAction before/after --- docs/ru/README.md | 2 ++ docs/ru/api/README.md | 17 ++++++++++++++++- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/docs/ru/README.md b/docs/ru/README.md index 4b6656521..cdc6b6bdf 100644 --- a/docs/ru/README.md +++ b/docs/ru/README.md @@ -1,5 +1,7 @@ # Что такое Vuex? + + Vuex — **паттерн управления состоянием + библиотека** для приложений на Vue.js. Он служит централизованным хранилищем данных для всех компонентов приложения с правилами, гарантирующими, что состояние может быть изменено только предсказуемым образом. Vuex интегрируется с официальным расширением [vue-devtools](https://github.com/vuejs/vue-devtools), предоставляя «из коробки» такие продвинутые возможности, как «машину времени» для отладки и экспорт/импорт слепков состояния данных. ### Что такое «паттерн управления состоянием»? diff --git a/docs/ru/api/README.md b/docs/ru/api/README.md index ac5f117dc..93256d883 100644 --- a/docs/ru/api/README.md +++ b/docs/ru/api/README.md @@ -120,7 +120,7 @@ const store = new Vuex.Store({ ...options }); * тип: `Boolean` - Интеграция в devtools конкретного экземпляра Vuex. Например, передача `false` сообщает экземпляру хранилища Vuex, что не требуется подписываться на плагин devtools. Это будет полезно если у вас несколько хранилищ на одной странице. + Интеграция в devtools конкретного экземпляра Vuex. Например, передача `false` сообщает экземпляру хранилища Vuex, что не требуется подписываться на плагин devtools. Это будет полезно если у вас несколько хранилищ на одной странице. ``` js { @@ -206,6 +206,21 @@ store.subscribeAction((action, state) => { Для прекращения отслеживания, необходимо вызвать возвращаемую методом функцию. +> Добавлено в версии 3.1.0 + +Начиная с версии 3.1.0, в `subscribeAction` также можно определять, должен ли обработчик вызываться *до* или *после* вызова действия (по умолчанию поведение *до*): + +``` js +store.subscribeAction({ + before: (action, state) => { + console.log(`before action ${action.type}`) + }, + after: (action, state) => { + console.log(`after action ${action.type}`) + } +}) +``` + Чаще всего используется в плагинах. [Подробнее](../guide/plugins.md) ### registerModule From a6973fabd145e45f1af9dbc5ac9fe440dd86290e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8B=BE=E4=B8=89=E8=82=A1=E5=9B=9B?= Date: Tue, 29 Jan 2019 21:58:14 +0800 Subject: [PATCH 02/29] docs: fixed links to vm. (#1465) --- docs/api/README.md | 2 +- docs/zh/api/README.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/api/README.md b/docs/api/README.md index e28ce1921..c859f876c 100644 --- a/docs/api/README.md +++ b/docs/api/README.md @@ -169,7 +169,7 @@ const store = new Vuex.Store({ ...options }) - `watch(fn: Function, callback: Function, options?: Object): Function` - Reactively watch `fn`'s return value, and call the callback when the value changes. `fn` receives the store's state as the first argument, and getters as the second argument. Accepts an optional options object that takes the same options as [Vue's `vm.$watch` method](https://vuejs.org/v2/api/#watch). + Reactively watch `fn`'s return value, and call the callback when the value changes. `fn` receives the store's state as the first argument, and getters as the second argument. Accepts an optional options object that takes the same options as [Vue's `vm.$watch` method](https://vuejs.org/v2/api/#vm-watch). To stop watching, call the returned unwatch function. diff --git a/docs/zh/api/README.md b/docs/zh/api/README.md index e1296acc2..8b775bf16 100644 --- a/docs/zh/api/README.md +++ b/docs/zh/api/README.md @@ -170,7 +170,7 @@ const store = new Vuex.Store({ ...options }) - `watch(fn: Function, callback: Function, options?: Object): Function` -  响应式地侦听 `fn` 的返回值,当值改变时调用回调函数。`fn` 接收 store 的 state 作为第一个参数,其 getter 作为第二个参数。最后接收一个可选的对象参数表示 Vue 的 [`vm.$watch`](https://cn.vuejs.org/v2/api/#watch) 方法的参数。 +  响应式地侦听 `fn` 的返回值,当值改变时调用回调函数。`fn` 接收 store 的 state 作为第一个参数,其 getter 作为第二个参数。最后接收一个可选的对象参数表示 Vue 的 [`vm.$watch`](https://cn.vuejs.org/v2/api/#vm-watch) 方法的参数。  要停止侦听,调用此方法返回的函数即可停止侦听。 From 64255700689ed16b6e4b606d05051f0fb931faed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8B=BE=E4=B8=89=E8=82=A1=E5=9B=9B?= Date: Wed, 30 Jan 2019 17:09:01 +0800 Subject: [PATCH 03/29] docs(zh): new subscribeAction options (#1495) --- docs/zh/api/README.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/docs/zh/api/README.md b/docs/zh/api/README.md index 8b775bf16..3378a320b 100644 --- a/docs/zh/api/README.md +++ b/docs/zh/api/README.md @@ -208,6 +208,21 @@ const store = new Vuex.Store({ ...options }) 要停止订阅,调用此方法返回的函数即可停止订阅。 + > 3.1.0 新增 + + 从 3.1.0 起,`subscribeAction` 也可以指定订阅处理函数的被调用时机应该在一个 action 分发*之前*还是*之后* (默认行为是*之前*): + + ``` js + store.subscribeAction({ + before: (action, state) => { + console.log(`before action ${action.type}`) + }, + after: (action, state) => { + console.log(`after action ${action.type}`) + } + }) + ``` + 该功能常用于插件。[详细介绍](../guide/plugins.md) ### registerModule From 9698dfd4fbce20e1032de07ba50db44a3dda22f9 Mon Sep 17 00:00:00 2001 From: Rogerio Angeliski Date: Wed, 30 Jan 2019 07:31:05 -0200 Subject: [PATCH 04/29] Removed english from translated guide (#1476) --- docs/ptbr/guide/modules.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/docs/ptbr/guide/modules.md b/docs/ptbr/guide/modules.md index 2e05e3308..8b3d5d7ea 100644 --- a/docs/ptbr/guide/modules.md +++ b/docs/ptbr/guide/modules.md @@ -307,8 +307,6 @@ Você também pode remover um módulo dinamicamente registrado com o `store.unre Se usarmos um objeto simples para declarar o estado do módulo, esse objeto de estado será compartilhado por referência e causará poluição entre estados de _store_/módulo quando ele sofrer uma mutação. -This is actually the exact same problem with `data` inside Vue components. So the solution is also the same - use a function for declaring module state (supported in 2.3.0+): - Este é exatamente o mesmo problema com _data_ dentro dos componentes do Vue. Então a solução também é a mesma - use uma função para declarar o estado do módulo (suportado em 2.3.0+): ``` js From 31dec55ea35611ac1244a9528ef3289ca5b7e200 Mon Sep 17 00:00:00 2001 From: periscuelo Date: Thu, 31 Jan 2019 09:18:21 -0200 Subject: [PATCH 05/29] docs: Update to version 3.1.0 [pt-br] (#1481) * First Commit * Translated the inital files * Translated the api docs * Translate some files * Translate some more files * One more file * made some fixes in translation * made some fixes in translation * make some fixes and translates * Add more translations and fixes * Add more translations and fixes * Add the last file translated * Update store pattern link * Removing conflicts * removing the forgotten english text * Updated docs to 3.1.0 * Update docs/ptbr/api/README.md Suggestion by ErickPetru Co-Authored-By: periscuelo * Update docs/ptbr/api/README.md Suggestion by ErickPetru Co-Authored-By: periscuelo * Update docs/ptbr/guide/modules.md Suggestion by ErickPetru Co-Authored-By: periscuelo --- docs/ptbr/README.md | 4 +++- docs/ptbr/api/README.md | 28 ++++++++++++++++++++++++++++ docs/ptbr/guide/modules.md | 2 +- 3 files changed, 32 insertions(+), 2 deletions(-) diff --git a/docs/ptbr/README.md b/docs/ptbr/README.md index 39e352450..32930a20b 100644 --- a/docs/ptbr/README.md +++ b/docs/ptbr/README.md @@ -1,5 +1,7 @@ # O que é Vuex? + + O Vuex é um **padrão de gerenciamento de estado + biblioteca** para aplicativos Vue.js. Ele serve como um _store_ centralizado para todos os componentes em uma aplicação, com regras garantindo que o estado só possa ser mutado de forma previsível. Ele também se integra com a extensão oficial [Vue devtools](https://github.com/vuejs/vue-devtools) para fornecer recursos avançados sem configurações adicionais, como depuração viajando pelo histórico de estado (_time travel_) e exportação/importação de registros de estado em determinado momento. ### O que é um "Padrão de Gerenciamento do Estado"? @@ -58,6 +60,6 @@ Esta é a ideia básica por trás do Vuex, inspirada por [Flux](https://facebook Embora o Vuex nos ajude a lidar com o gerenciamento de estado compartilhado, ele também vem com o custo de mais conceitos e códigos repetitivos. É uma escolha de prós e contras entre produtividade de curto e longo prazo -Se você nunca construiu um SPA em grande escala e for direto para o Vuex, ele pode parecer detalhado e desanimador. Isso é perfeitamente normal - se o seu aplicativo é simples, você provavelmente ficará bem sem o Vuex. Um simples [global event bus](https://br.vuejs.org/v2/guide/components.html#Comunicacao-Nao-Pai-Filho) pode ser tudo que você precisa. Mas, se você está criando um SPA de médio a grande porte, é provável que tenha encontrado situações que fazem você pensar em como lidar melhor com o estado fora de seus componentes do Vue, e o Vuex será o próximo passo natural para você. Há uma boa citação de Dan Abramov, o autor do Redux: +Se você nunca construiu um SPA em grande escala e for direto para o Vuex, ele pode parecer detalhado e desanimador. Isso é perfeitamente normal - se o seu aplicativo é simples, você provavelmente ficará bem sem o Vuex. Um simples [store pattern](https://br.vuejs.org/v2/guide/state-management.html#Gerenciamento-de-Estado-do-Zero) pode ser tudo que você precisa. Mas, se você está criando um SPA de médio a grande porte, é provável que tenha encontrado situações que fazem você pensar em como lidar melhor com o estado fora de seus componentes do Vue, e o Vuex será o próximo passo natural para você. Há uma boa citação de Dan Abramov, o autor do Redux: > As bibliotecas _Flux_ são como óculos: você saberá quando precisar delas. diff --git a/docs/ptbr/api/README.md b/docs/ptbr/api/README.md index 4b48309a9..5c8009909 100644 --- a/docs/ptbr/api/README.md +++ b/docs/ptbr/api/README.md @@ -116,6 +116,19 @@ const store = new Vuex.Store({ ...options }) [Detalhes](../guide/strict.md) +### devtools + +- type: `Boolean` + + Ative ou desative as ferramentas de desenvolvedor para uma determinada instância vuex. Passar _false_ à instância diz ao _store_ Vuex para não se integrar ao _devtools_. Útil para quando se tem vários _stores_ em uma _single page_. + + ``` js + { + devtools: false + } + ``` + + ## Vuex.Store Propriedades da Instância ### state @@ -194,6 +207,21 @@ const store = new Vuex.Store({ ...options }) Para cancelar a assinatura, chame a função _unsubscribe_ retornada. + > Novo em 3.1.0 + + A partir da 3.1.0, `subscribeAction` também pode especificar se o manipulador do _subscribe_ deve ser chamado *antes de* ou *depois de* um despacho de ação (o comportamento padrão é *antes*): + + ``` js + store.subscribeAction({ + before: (action, state) => { + console.log(`antes da action ${action.type}`) + }, + after: (action, state) => { + console.log(`depois da action ${action.type}`) + } + }) + ``` + Mais comumente usado em plugins. [Detalhes](../guide/plugins.md) ### registerModule diff --git a/docs/ptbr/guide/modules.md b/docs/ptbr/guide/modules.md index 8b3d5d7ea..8c934fef0 100644 --- a/docs/ptbr/guide/modules.md +++ b/docs/ptbr/guide/modules.md @@ -307,7 +307,7 @@ Você também pode remover um módulo dinamicamente registrado com o `store.unre Se usarmos um objeto simples para declarar o estado do módulo, esse objeto de estado será compartilhado por referência e causará poluição entre estados de _store_/módulo quando ele sofrer uma mutação. -Este é exatamente o mesmo problema com _data_ dentro dos componentes do Vue. Então a solução também é a mesma - use uma função para declarar o estado do módulo (suportado em 2.3.0+): +Este é exatamente o mesmo problema com `data` dentro dos componentes Vue. Então, a solução também é a mesma - use uma função para declarar o estado do módulo (suportado em 2.3.0+): ``` js const MyReusableModule = { From 85ab92e662f69e2f006b3f2fcb7e268acc273888 Mon Sep 17 00:00:00 2001 From: Fernanda Sales Bittencourt de Lemos Date: Thu, 31 Jan 2019 11:11:01 -0200 Subject: [PATCH 06/29] complement preserveState section (#1484) --- docs/guide/modules.md | 4 ++++ docs/ptbr/guide/modules.md | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/docs/guide/modules.md b/docs/guide/modules.md index ac0853621..161591b02 100644 --- a/docs/guide/modules.md +++ b/docs/guide/modules.md @@ -295,8 +295,12 @@ Dynamic module registration makes it possible for other Vue plugins to also leve You can also remove a dynamically registered module with `store.unregisterModule(moduleName)`. Note you cannot remove static modules (declared at store creation) with this method. +#### Preserving state + It may be likely that you want to preserve the previous state when registering a new module, such as preserving state from a Server Side Rendered app. You can achieve this with `preserveState` option: `store.registerModule('a', module, { preserveState: true })` +When you set `preserveState: true`, the module is registered, actions, mutations and getters are added to the store, but the state not. It's assumed that your store state already contains state for that module and you don't want to overwrite it. + ### Module Reuse Sometimes we may need to create multiple instances of a module, for example: diff --git a/docs/ptbr/guide/modules.md b/docs/ptbr/guide/modules.md index 8c934fef0..54c3365f3 100644 --- a/docs/ptbr/guide/modules.md +++ b/docs/ptbr/guide/modules.md @@ -296,8 +296,12 @@ O registro de módulo dinâmico possibilita que outros plug-ins Vue aproveitem t Você também pode remover um módulo dinamicamente registrado com o `store.unregisterModule(moduleName)`. Note que você não pode remover módulos estáticos (declarados na criação do _store_) com este método. +#### Preservando o estado + É bem provável que você queira preservar o estado anterior ao registrar um novo módulo, como preservar o estado de um aplicativo Renderizado no Lado do Servidor (_Server_ _Side_ _Rendered_). Você pode fazer isso com a opção `preserveState`:`store.registerModule('a', module, {preserveState: true})` +Quando você informa `preserveState: true`, o módulo é registrado, as ações, mutações e _getters_ são incluídos no _store_, mas o estado não. É assumido que estado da sua _store_ já contém um estado para aquele módulo e você não quer sobrescrevê-lo. + ### Reutilização do Módulo Às vezes, podemos precisar criar várias instâncias de um módulo, por exemplo: From 52fe045cb9d12e0a50c2b1a9110eea0e9deb3228 Mon Sep 17 00:00:00 2001 From: kazuya kawaguchi Date: Thu, 31 Jan 2019 22:42:33 +0900 Subject: [PATCH 07/29] docs: update ja docs (#1497) * docs(ja): update plugin.md ref: https://github.com/vuejs/vuex/commit/3d3e4e061ccbc6c84a684380ab5074c5418be1a7 * docs(ja): update api/README.md ref: https://github.com/vuejs/vuex/commit/be75d41cf54d50177a7db7e9218e8d1c820ae830 * docs(ja): translate previous commit * docs(ja): add link ref: https://github.com/vuejs/vuex/commit/bd23b9ad37151085ae4cb8d0456be0812a3f03ce * docs(ja): update hot-reload.md ref: https://github.com/vuejs/vuex/commit/ee7c6f3b60f5665f7aaf10a7e9fd49366cc01476 * docs(ja): remove stage-3 ref: https://github.com/vuejs/vuex/commit/de0515254ccd25268df93477f36702472da9e83f * docs(ja): add sentence from en docs ref: https://github.com/vuejs/vuex/commit/095ccc396a7fb81613f0b9ff374b6c610b186c3e * docs(ja): translate previous commit * docs(ja): add video * docs(ja): replce component ref: https://github.com/vuejs/vuex/commit/2dfdd83ea55e5169f640b6cf1d0e4d1a2cee2bfb * docs(ja): add new API docs ref: https://github.com/vuejs/vuex/commit/431540b4637f367698f4849f91d5d326fd9c35b7 * docs(ja): translate previous commit --- docs/ja/README.md | 2 ++ docs/ja/api/README.md | 34 ++++++++++++++++++++++++++++++++-- docs/ja/guide/actions.md | 2 +- docs/ja/guide/hot-reload.md | 2 +- docs/ja/guide/mutations.md | 2 +- docs/ja/guide/plugins.md | 2 +- 6 files changed, 38 insertions(+), 6 deletions(-) diff --git a/docs/ja/README.md b/docs/ja/README.md index f1b0e21ba..88d3e3c5b 100644 --- a/docs/ja/README.md +++ b/docs/ja/README.md @@ -1,5 +1,7 @@ # Vuex とは何か? + + Vuex は Vue.js アプリケーションのための **状態管理パターン + ライブラリ**です。 これは予測可能な方法によってのみ状態の変異を行うというルールを保証し、アプリケーション内の全てのコンポーネントのための集中型のストアとして機能します。 また Vue 公式の[開発ツール拡張](https://github.com/vuejs/vue-devtools)と連携し、設定なしでタイムトラベルデバッグやステートのスナップショットのエクスポートやインポートのような高度な機能を提供します。 diff --git a/docs/ja/api/README.md b/docs/ja/api/README.md index 250363b49..43afe97c7 100644 --- a/docs/ja/api/README.md +++ b/docs/ja/api/README.md @@ -116,6 +116,19 @@ const store = new Vuex.Store({ ...options }) [詳細](../guide/strict.md) + +### devtools + + - 型: `Boolean` + + 特定の Vuex インスタンスに対して開発ツールをオン、またはオフにします。インスタンスに false を渡すと、開発ツールのプラグインを購読しないように Vuex ストアに伝えます。1 ページに複数のストアがある場合に便利です。 + + ``` js + { + devtools: false + } + ``` + ## Vuex.Store インスタンスプロパティ ### state @@ -156,7 +169,7 @@ const store = new Vuex.Store({ ...options }) - **`watch(fn: Function, callback: Function, options?: Object): Function`** - `fn`が返す値をリアクティブに監視し、値が変わった時にコールバックを呼びます。`fn`は最初の引数としてストアのステートを、2番目の引数としてゲッターを受け取ります。 Vue の`vm.$watch`メソッドと同じオプションをオプションのオブジェクトとして受け付けます。 + `fn`が返す値をリアクティブに監視し、値が変わった時にコールバックを呼びます。`fn`は最初の引数としてストアのステートを、2番目の引数としてゲッターを受け取ります。 [Vue の`vm.$watch`メソッド](https://jp.vuejs.org/v2/api/#watch)と同じオプションをオプションのオブジェクトとして受け付けます。 監視を止める場合は、返された unwatch 関数を呼び出します。 @@ -192,7 +205,24 @@ const store = new Vuex.Store({ ...options }) }) ``` - プラグインで最も一般的に使用されます。[Details](../guide/plugins.md) + 購読を停止するには、返された購読解除関数を呼びます。 + + > 3.1.0 で新規追加 + + 3.1.0 から、`subscribeAction` は購読ハンドラがアクションディスパッチの*前 (before)*、または*後 (after)*に呼びだすべきかどうか(デフォルトの動作は、*before* です)指定することもできます。 + + ``` js + store.subscribeAction({ + before: (action, state) => { + console.log(`before action ${action.type}`) + }, + after: (action, state) => { + console.log(`after action ${action.type}`) + } + }) + ``` + + プラグインで最も一般的に使用されます。[詳細](../guide/plugins.md) ### registerModule diff --git a/docs/ja/guide/actions.md b/docs/ja/guide/actions.md index 5ef205768..a37242917 100644 --- a/docs/ja/guide/actions.md +++ b/docs/ja/guide/actions.md @@ -25,7 +25,7 @@ const store = new Vuex.Store({ }) ``` -アクションハンドラはストアインスタンスのメソッドやプロパティのセットと同じものを呼び出せるコンテキストオブジェクトを受け取ります。したがって `context.commit` を呼び出すことでミューテーションをコミットできます。あるいは `context.state` や `context.getters` で、状態やゲッターにアクセスできます。なぜコンテキストオブジェクトがストアインスタンスそのものではないのかは、後ほど[モジュール](modules.md)で説明します。 +アクションハンドラはストアインスタンスのメソッドやプロパティのセットと同じものを呼び出せるコンテキストオブジェクトを受け取ります。したがって `context.commit` を呼び出すことでミューテーションをコミットできます。あるいは `context.state` や `context.getters` で、状態やゲッターにアクセスできます。他のアクションも `context.dispatch` で呼ぶこともできます。なぜコンテキストオブジェクトがストアインスタンスそのものではないのかは、後ほど[モジュール](modules.md)で説明します。 実際にはコードを少しシンプルにするために ES2015 の[引数分割束縛(argument destructuring)](https://github.com/lukehoban/es6features#destructuring)がよく使われます(特に `commit` を複数回呼び出す必要があるとき): diff --git a/docs/ja/guide/hot-reload.md b/docs/ja/guide/hot-reload.md index cfc7c5791..8283537fd 100644 --- a/docs/ja/guide/hot-reload.md +++ b/docs/ja/guide/hot-reload.md @@ -30,7 +30,7 @@ if (module.hot) { // babel 6 のモジュール出力のため、ここでは .default を追加しなければならない const newActions = require('./actions').default const newMutations = require('./mutations').default - // 新しいアクションとミューテーションにスワップ + // 新しいモジュールとミューテーションにスワップ store.hotUpdate({ mutations: newMutations, modules: { diff --git a/docs/ja/guide/mutations.md b/docs/ja/guide/mutations.md index 77d6c864d..967ce9db2 100644 --- a/docs/ja/guide/mutations.md +++ b/docs/ja/guide/mutations.md @@ -88,7 +88,7 @@ Vuex ストアの状態は Vue によってリアクティブになっている - `Vue.set(obj, 'newProp', 123)` を使用する。あるいは - - 全く新しいオブジェクトで既存のオブジェクトを置き換える。例えば、stage-3 の[スプレッドシンタックス(object spread syntax)](https://github.com/sebmarkbage/ecmascript-rest-spread) を使用して、次のように書くことができます: + - 全く新しいオブジェクトで既存のオブジェクトを置き換える。例えば、[スプレッドシンタックス(object spread syntax)](https://github.com/sebmarkbage/ecmascript-rest-spread) を使用して、次のように書くことができます: ``` js state.obj = { ...state.obj, newProp: 123 } diff --git a/docs/ja/guide/plugins.md b/docs/ja/guide/plugins.md index db4cf6f30..9ac7da452 100644 --- a/docs/ja/guide/plugins.md +++ b/docs/ja/guide/plugins.md @@ -25,7 +25,7 @@ const store = new Vuex.Store({ プラグインは直接、状態を変更できません。これはコンポーネントに似ています。プラグインはコンポーネント同様に、ミューテーションのコミットによる変更のトリガーだけで状態を変更できます。 -ミューテーションのコミットによるストアとデータソースの同期をプラグインで実現できます。 websocket データソースとストアを例にします (これは不自然な例です。実際には、さらに複雑なタスクのために `createPlugin` 関数は、追加でいくつかのオプションを受け取れます): +ミューテーションのコミットによるストアとデータソースの同期をプラグインで実現できます。 websocket データソースとストアを例にします (これは不自然な例です。実際には、さらに複雑なタスクのために `createWebSocketPlugin` 関数は、追加でいくつかのオプションを受け取れます): ``` js export default function createWebSocketPlugin (socket) { From 9c03cce57f6bbcc3e0de5e80452538ea91b72f52 Mon Sep 17 00:00:00 2001 From: Alexander Sokolov Date: Sun, 10 Feb 2019 12:24:59 +0300 Subject: [PATCH 08/29] docs: [RU] Translation update (#1499) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * structure.md исправлена опечатка * actions.md мелкие правки * api.md мелкие правки * intro.md мелкие правки * state.md мелкие правки * strict.md мелкие правки * testing.md мелкие правки * actions.md правки * testing.md правки * Fix typos. ru * SUMMARY.md правки заголовков * Минусы на тире * [RU] Moved to VuePress * Fix & single quotes * [RU] Update * Remove settings.json * fix link * fix images links * translated ru image and ai sources * Localized images * README.md исправлена ссылка * api: formatting example * api: fix links * docs: remove core-concepts.md * modules.md правка примеров * docs: [RU] fix links anchors * docs: (ru) plugins.md fix * api.md добавлен devtools * api.md добавлена ссылка * api.md обновление * installation.md обновление * README.md обновление * getting-started.md удален, дубль * README.md обновление * installation.md изменена ссылка * README.md правка * state.md обновление * state.md правки * getters.md правки * README.md fix * state.md fix * state.md правки * hot-reload.md правка * mutations.md правка * README.md add video-preview component * api/README.md added about subscribeAction before/after * modules.md update --- docs/ru/guide/modules.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/ru/guide/modules.md b/docs/ru/guide/modules.md index b4f53cd10..f080afc5a 100644 --- a/docs/ru/guide/modules.md +++ b/docs/ru/guide/modules.md @@ -292,7 +292,11 @@ store.registerModule(['nested', 'myModule'], { Удалить динамически зарегистрированный модуль можно с помощью `store.unregisterModule(moduleName)`. Обратите внимание, что статические (определённые на момент создания хранилища) модули при помощи этого метода удалить не получится. -Вероятно, вы хотите сохранить предыдущее состояние при регистрации нового модуля, например сохранить состояние из приложения с рендерингом на стороне сервера. Вы можете этого добиться с помощью опции `preserveState`: `store.registerModule('a', module, { preserveState: true })` +#### Сохранение состояния + +Вероятно, вы хотите сохранить предыдущее состояние при регистрации нового модуля, например сохранить состояние из приложения с рендерингом на стороне сервера. Вы можете этого добиться с помощью опции `preserveState`: `store.registerModule('a', module, { preserveState: true })`. + +При использовании `preserveState: true` модуль регистрируется, действия, мутации и геттеры добавляются в хранилище, а состояние нет. Предполагается, что состояние вашего хранилища уже содержит состояние для этого модуля и нет необходимости его перезаписывать. ### Повторное использование модулей From 9dd8000bf8bc5d795c2e4c5d526d3c10a3d8fd4e Mon Sep 17 00:00:00 2001 From: Awater Date: Wed, 13 Feb 2019 23:21:15 +0800 Subject: [PATCH 09/29] docs(zh): fix a typo (#1501) --- docs/zh/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/zh/README.md b/docs/zh/README.md index bc0e73ba9..c0c093f34 100644 --- a/docs/zh/README.md +++ b/docs/zh/README.md @@ -50,7 +50,7 @@ new Vue({ 另外,通过定义和隔离状态管理中的各种概念并强制遵守一定的规则,我们的代码将会变得更结构化且易维护。 -这就是 Vuex 背后的基本思想,借鉴了 [Flux](https://facebook.github.io/flux/docs/overview.html)、[Redux](http://redux.js.org/)、和 [The Elm Architecture](https://guide.elm-lang.org/architecture/)。与其他模式不同的是,Vuex 是专门为 Vue.js 设计的状态管理库,以利用 Vue.js 的细粒度数据响应机制来进行高效的状态更新。 +这就是 Vuex 背后的基本思想,借鉴了 [Flux](https://facebook.github.io/flux/docs/overview.html)、[Redux](http://redux.js.org/)和 [The Elm Architecture](https://guide.elm-lang.org/architecture/)。与其他模式不同的是,Vuex 是专门为 Vue.js 设计的状态管理库,以利用 Vue.js 的细粒度数据响应机制来进行高效的状态更新。 ![vuex](/vuex.png) From a18fa314dd895bfeea6724653e2fe25557b257d1 Mon Sep 17 00:00:00 2001 From: Tao Date: Wed, 13 Feb 2019 23:23:17 +0800 Subject: [PATCH 10/29] chore: support jsdelivr npm cdn like vue package does (#1496) --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index 6ed745e46..375ada242 100644 --- a/package.json +++ b/package.json @@ -5,6 +5,7 @@ "main": "dist/vuex.common.js", "module": "dist/vuex.esm.js", "unpkg": "dist/vuex.js", + "jsdelivr": "dist/vuex.js", "typings": "types/index.d.ts", "files": [ "dist", From 31e4fbc8ac0e0f3a39fc4350667c3821bfec6036 Mon Sep 17 00:00:00 2001 From: Sylvain Pace Date: Wed, 13 Feb 2019 16:27:31 +0100 Subject: [PATCH 11/29] docs: enabling DocSearch https://github.com/algolia/docsearch-configs/commit/0b171ddf626dac501b2d9bf4a80e79613c874918 (#1472) --- docs/.vuepress/config.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/.vuepress/config.js b/docs/.vuepress/config.js index 98e4b79d5..c67d10273 100644 --- a/docs/.vuepress/config.js +++ b/docs/.vuepress/config.js @@ -39,6 +39,10 @@ module.exports = { serviceWorker: true, theme: 'vue', themeConfig: { + algolia: { + apiKey: '97f135e4b5f5487fb53f0f2dae8db59d', + indexName: 'vuex', + }, repo: 'vuejs/vuex', docsDir: 'docs', locales: { From 1fd2fc4d8790ac34e327579dcbd4065d79b87e71 Mon Sep 17 00:00:00 2001 From: Jinjiang Date: Tue, 19 Feb 2019 00:24:39 +0800 Subject: [PATCH 12/29] docs(zh): update --- docs/zh/README.md | 2 +- docs/zh/guide/modules.md | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/zh/README.md b/docs/zh/README.md index c0c093f34..a58deffeb 100644 --- a/docs/zh/README.md +++ b/docs/zh/README.md @@ -50,7 +50,7 @@ new Vue({ 另外,通过定义和隔离状态管理中的各种概念并强制遵守一定的规则,我们的代码将会变得更结构化且易维护。 -这就是 Vuex 背后的基本思想,借鉴了 [Flux](https://facebook.github.io/flux/docs/overview.html)、[Redux](http://redux.js.org/)和 [The Elm Architecture](https://guide.elm-lang.org/architecture/)。与其他模式不同的是,Vuex 是专门为 Vue.js 设计的状态管理库,以利用 Vue.js 的细粒度数据响应机制来进行高效的状态更新。 +这就是 Vuex 背后的基本思想,借鉴了 [Flux](https://facebook.github.io/flux/docs/overview.html)、[Redux](http://redux.js.org/) 和 [The Elm Architecture](https://guide.elm-lang.org/architecture/)。与其他模式不同的是,Vuex 是专门为 Vue.js 设计的状态管理库,以利用 Vue.js 的细粒度数据响应机制来进行高效的状态更新。 ![vuex](/vuex.png) diff --git a/docs/zh/guide/modules.md b/docs/zh/guide/modules.md index c210d3c66..c5a27fa4c 100644 --- a/docs/zh/guide/modules.md +++ b/docs/zh/guide/modules.md @@ -294,8 +294,12 @@ store.registerModule(['nested', 'myModule'], { 你也可以使用 `store.unregisterModule(moduleName)` 来动态卸载模块。注意,你不能使用此方法卸载静态模块(即创建 store 时声明的模块)。 +#### 保留 state + 在注册一个新 module 时,你很有可能想保留过去的 state,例如从一个服务端渲染的应用保留 state。你可以通过 `preserveState` 选项将其归档:`store.registerModule('a', module, { preserveState: true })`。 +当你设置 `preserveState: true` 时,该模块会被注册,action、mutation 和 getter 会被添加到 store 中,但是 state 不会。这里假设 store 的 state 已经包含了这个 module 的 state 并且你不希望将其覆写。 + ### 模块重用 有时我们可能需要创建一个模块的多个实例,例如: From 665455f8daf8512e7adbf63c2842bc0b1e39efdb Mon Sep 17 00:00:00 2001 From: Igor Randjelovic Date: Mon, 18 Feb 2019 22:15:41 +0100 Subject: [PATCH 13/29] feat(devtool): allow usage in non-browser environments (#1404) --- src/plugins/devtool.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/plugins/devtool.js b/src/plugins/devtool.js index a6df685f0..dc6b04f73 100644 --- a/src/plugins/devtool.js +++ b/src/plugins/devtool.js @@ -1,6 +1,9 @@ -const devtoolHook = - typeof window !== 'undefined' && - window.__VUE_DEVTOOLS_GLOBAL_HOOK__ +const target = typeof window !== 'undefined' + ? window + : typeof global !== 'undefined' + ? global + : {} +const devtoolHook = target.__VUE_DEVTOOLS_GLOBAL_HOOK__ export default function devtoolPlugin (store) { if (!devtoolHook) return From 041df8da91a6f47a4029cab2d999b76f12f47660 Mon Sep 17 00:00:00 2001 From: Per Harald Borgen Date: Thu, 21 Feb 2019 20:16:27 +0100 Subject: [PATCH 14/29] docs: added Scrimba lessons (#1512) --- docs/.vuepress/override.styl | 32 ++++++++++++++++++++++++++++++++ docs/README.md | 2 ++ docs/fr/README.md | 2 ++ docs/fr/guide/README.md | 2 ++ docs/fr/guide/actions.md | 2 ++ docs/fr/guide/forms.md | 2 ++ docs/fr/guide/getters.md | 2 ++ docs/fr/guide/modules.md | 2 ++ docs/fr/guide/mutations.md | 2 ++ docs/fr/guide/plugins.md | 2 ++ docs/fr/guide/state.md | 4 ++++ docs/fr/guide/testing.md | 2 ++ docs/guide/README.md | 2 ++ docs/guide/actions.md | 2 ++ docs/guide/forms.md | 2 ++ docs/guide/getters.md | 2 ++ docs/guide/modules.md | 2 ++ docs/guide/mutations.md | 2 ++ docs/guide/plugins.md | 2 ++ docs/guide/state.md | 4 ++++ docs/guide/testing.md | 2 ++ docs/ja/README.md | 2 ++ docs/ja/guide/README.md | 2 ++ docs/ja/guide/actions.md | 2 ++ docs/ja/guide/forms.md | 2 ++ docs/ja/guide/getters.md | 2 ++ docs/ja/guide/modules.md | 2 ++ docs/ja/guide/mutations.md | 2 ++ docs/ja/guide/plugins.md | 2 ++ docs/ja/guide/state.md | 4 ++++ docs/ja/guide/testing.md | 2 ++ docs/kr/README.md | 2 ++ docs/kr/guide/README.md | 2 ++ docs/kr/guide/actions.md | 2 ++ docs/kr/guide/forms.md | 2 ++ docs/kr/guide/getters.md | 2 ++ docs/kr/guide/modules.md | 2 ++ docs/kr/guide/mutations.md | 2 ++ docs/kr/guide/plugins.md | 2 ++ docs/kr/guide/state.md | 4 ++++ docs/kr/guide/testing.md | 2 ++ docs/ptbr/README.md | 2 ++ docs/ptbr/guide/README.md | 2 ++ docs/ptbr/guide/actions.md | 2 ++ docs/ptbr/guide/forms.md | 2 ++ docs/ptbr/guide/getters.md | 2 ++ docs/ptbr/guide/modules.md | 2 ++ docs/ptbr/guide/mutations.md | 2 ++ docs/ptbr/guide/plugins.md | 2 ++ docs/ptbr/guide/state.md | 4 ++++ docs/ptbr/guide/testing.md | 2 ++ docs/ru/README.md | 2 ++ docs/ru/guide/README.md | 2 ++ docs/ru/guide/actions.md | 2 ++ docs/ru/guide/forms.md | 2 ++ docs/ru/guide/getters.md | 2 ++ docs/ru/guide/modules.md | 2 ++ docs/ru/guide/mutations.md | 2 ++ docs/ru/guide/plugins.md | 2 ++ docs/ru/guide/state.md | 4 ++++ docs/ru/guide/testing.md | 2 ++ docs/zh/README.md | 2 ++ docs/zh/guide/README.md | 2 ++ docs/zh/guide/actions.md | 2 ++ docs/zh/guide/forms.md | 2 ++ docs/zh/guide/getters.md | 2 ++ docs/zh/guide/modules.md | 2 ++ docs/zh/guide/mutations.md | 2 ++ docs/zh/guide/plugins.md | 2 ++ docs/zh/guide/state.md | 4 ++++ docs/zh/guide/testing.md | 2 ++ 71 files changed, 186 insertions(+) create mode 100644 docs/.vuepress/override.styl diff --git a/docs/.vuepress/override.styl b/docs/.vuepress/override.styl new file mode 100644 index 000000000..7222c4be1 --- /dev/null +++ b/docs/.vuepress/override.styl @@ -0,0 +1,32 @@ +.scrimba + background-color #e7ecf3 + padding 1em 1.25em + border-radius 2px + color #486491 + position relative + margin-top: 16px + a + color #486491 !important + position relative + padding-left 36px + &:before + content '' + position absolute + display block + width 30px + height 30px + top -5px + left -4px + border-radius 50% + background-color #73abfe + &:after + content '' + position absolute + display block + width 0 + height 0 + top 5px + left 8px + border-top 5px solid transparent + border-bottom 5px solid transparent + border-left 8px solid #fff \ No newline at end of file diff --git a/docs/README.md b/docs/README.md index 3cddf78d3..67283092e 100644 --- a/docs/README.md +++ b/docs/README.md @@ -54,6 +54,8 @@ In addition, by defining and separating the concepts involved in state managemen This is the basic idea behind Vuex, inspired by [Flux](https://facebook.github.io/flux/docs/overview.html), [Redux](http://redux.js.org/) and [The Elm Architecture](https://guide.elm-lang.org/architecture/). Unlike the other patterns, Vuex is also a library implementation tailored specifically for Vue.js to take advantage of its granular reactivity system for efficient updates. +If you want to learn Vuex in an interactive way you can check out this [Vuex course on Scrimba](https://scrimba.com/g/gvuex), which gives you a mix of screencast and code playground that you can pause and play around with anytime. + ![vuex](/vuex.png) ### When Should I Use It? diff --git a/docs/fr/README.md b/docs/fr/README.md index 7ff74cb57..21aedb2bc 100644 --- a/docs/fr/README.md +++ b/docs/fr/README.md @@ -52,6 +52,8 @@ De plus, en définissant et en séparant les concepts impliqués dans la gestion 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. +Si vous voulez apprendre Vuex de manière interactive, jetez un oeil à ce [cours sur Vuex sur Scrimba.](https://scrimba.com/g/gvuex) + ![vuex](/vuex.png) ### Quand l'utiliser ? diff --git a/docs/fr/guide/README.md b/docs/fr/guide/README.md index 05c32dc2f..ce251fd86 100644 --- a/docs/fr/guide/README.md +++ b/docs/fr/guide/README.md @@ -1,5 +1,7 @@ # Pour commencer + + 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 l'état, ils se mettront à jour de façon réactive et efficace si l'état du store a changé. diff --git a/docs/fr/guide/actions.md b/docs/fr/guide/actions.md index ebeacc803..2cc82bdd2 100644 --- a/docs/fr/guide/actions.md +++ b/docs/fr/guide/actions.md @@ -1,5 +1,7 @@ # Actions + + Les actions sont similaires aux mutations, à la différence que : - Au lieu de modifier l'état, les actions actent des mutations. diff --git a/docs/fr/guide/forms.md b/docs/fr/guide/forms.md index f304def1c..3d8dfef5e 100644 --- a/docs/fr/guide/forms.md +++ b/docs/fr/guide/forms.md @@ -1,5 +1,7 @@ # Gestion des formulaires + + 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 diff --git a/docs/fr/guide/getters.md b/docs/fr/guide/getters.md index b6d6eed7c..1b70f8972 100644 --- a/docs/fr/guide/getters.md +++ b/docs/fr/guide/getters.md @@ -1,5 +1,7 @@ # Accesseurs + + 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 diff --git a/docs/fr/guide/modules.md b/docs/fr/guide/modules.md index 39eb9edc8..8c51472fa 100644 --- a/docs/fr/guide/modules.md +++ b/docs/fr/guide/modules.md @@ -1,5 +1,7 @@ # Modules + + 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 états, mutations, actions, accesseurs. Il peut même contenir ses propres modules internes. diff --git a/docs/fr/guide/mutations.md b/docs/fr/guide/mutations.md index 3b867d250..edc1f8261 100644 --- a/docs/fr/guide/mutations.md +++ b/docs/fr/guide/mutations.md @@ -1,5 +1,7 @@ # 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 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 diff --git a/docs/fr/guide/plugins.md b/docs/fr/guide/plugins.md index 30aab77c0..56df03a3a 100644 --- a/docs/fr/guide/plugins.md +++ b/docs/fr/guide/plugins.md @@ -1,5 +1,7 @@ # Plugins + + Les stores Vuex prennent une option `plugins` qui expose des hooks pour chaque mutation. Un plugin Vuex est simplement une fonction qui reçoit un store comme unique argument : ``` js diff --git a/docs/fr/guide/state.md b/docs/fr/guide/state.md index 59ce19b02..63ea28263 100644 --- a/docs/fr/guide/state.md +++ b/docs/fr/guide/state.md @@ -2,6 +2,8 @@ ### Arbre d'état unique + + 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. 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. @@ -58,6 +60,8 @@ 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 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 diff --git a/docs/fr/guide/testing.md b/docs/fr/guide/testing.md index f0cae2b10..9682e8ba9 100644 --- a/docs/fr/guide/testing.md +++ b/docs/fr/guide/testing.md @@ -1,5 +1,7 @@ # Tests + + Les parties principales que l'on veut couvrir par des tests unitaires avec Vuex sont les mutations et les actions. ### Tester les mutations diff --git a/docs/guide/README.md b/docs/guide/README.md index 496c665f7..45882a5c3 100644 --- a/docs/guide/README.md +++ b/docs/guide/README.md @@ -1,5 +1,7 @@ # Getting Started + + At the center of every Vuex application is the **store**. A "store" is basically a container that holds your application **state**. There are two things that make a Vuex store different from a plain global object: 1. Vuex stores are reactive. When Vue components retrieve state from it, they will reactively and efficiently update if the store's state changes. diff --git a/docs/guide/actions.md b/docs/guide/actions.md index b022332e2..7bf4fc933 100644 --- a/docs/guide/actions.md +++ b/docs/guide/actions.md @@ -1,5 +1,7 @@ # Actions + + Actions are similar to mutations, the differences being that: - Instead of mutating the state, actions commit mutations. diff --git a/docs/guide/forms.md b/docs/guide/forms.md index 37fd58e56..d9d4d586f 100644 --- a/docs/guide/forms.md +++ b/docs/guide/forms.md @@ -1,5 +1,7 @@ # Form Handling + + When using Vuex in strict mode, it could be a bit tricky to use `v-model` on a piece of state that belongs to Vuex: ``` html diff --git a/docs/guide/getters.md b/docs/guide/getters.md index 124f38fac..981901efc 100644 --- a/docs/guide/getters.md +++ b/docs/guide/getters.md @@ -1,5 +1,7 @@ # Getters + + Sometimes we may need to compute derived state based on store state, for example filtering through a list of items and counting them: ``` js diff --git a/docs/guide/modules.md b/docs/guide/modules.md index 161591b02..8715ce748 100644 --- a/docs/guide/modules.md +++ b/docs/guide/modules.md @@ -1,5 +1,7 @@ # Modules + + Due to using a single state tree, all state of our application is contained inside one big object. However, as our application grows in scale, the store can get really bloated. To help with that, Vuex allows us to divide our store into **modules**. Each module can contain its own state, mutations, actions, getters, and even nested modules - it's fractal all the way down: diff --git a/docs/guide/mutations.md b/docs/guide/mutations.md index 965d0c62c..8c206529c 100644 --- a/docs/guide/mutations.md +++ b/docs/guide/mutations.md @@ -1,5 +1,7 @@ # Mutations + + The only way to actually change state in a Vuex store is by committing a mutation. Vuex mutations are very similar to events: each mutation has a string **type** and a **handler**. The handler function is where we perform actual state modifications, and it will receive the state as the first argument: ``` js diff --git a/docs/guide/plugins.md b/docs/guide/plugins.md index 22f937aa8..fe4939c0a 100644 --- a/docs/guide/plugins.md +++ b/docs/guide/plugins.md @@ -1,5 +1,7 @@ # Plugins + + Vuex stores accept the `plugins` option that exposes hooks for each mutation. A Vuex plugin is simply a function that receives the store as the only argument: ``` js diff --git a/docs/guide/state.md b/docs/guide/state.md index 40d477b08..b89c39bc9 100644 --- a/docs/guide/state.md +++ b/docs/guide/state.md @@ -2,6 +2,8 @@ ### Single State Tree + + Vuex uses a **single state tree** - that is, this single object contains all your application level state and serves as the "single source of truth". This also means usually you will have only one store for each application. A single state tree makes it straightforward to locate a specific piece of state, and allows us to easily take snapshots of the current app state for debugging purposes. The single state tree does not conflict with modularity - in later chapters we will discuss how to split your state and mutations into sub modules. @@ -58,6 +60,8 @@ const Counter = { ### The `mapState` Helper + + When a component needs to make use of multiple store state properties or getters, declaring all these computed properties can get repetitive and verbose. To deal with this we can make use of the `mapState` helper which generates computed getter functions for us, saving us some keystrokes: ``` js diff --git a/docs/guide/testing.md b/docs/guide/testing.md index 63b9d9120..3ca0bdf2d 100644 --- a/docs/guide/testing.md +++ b/docs/guide/testing.md @@ -1,5 +1,7 @@ # Testing + + The main parts we want to unit test in Vuex are mutations and actions. ### Testing Mutations diff --git a/docs/ja/README.md b/docs/ja/README.md index 88d3e3c5b..086217eb1 100644 --- a/docs/ja/README.md +++ b/docs/ja/README.md @@ -57,6 +57,8 @@ new Vue({ これが Vuex の背景にある基本的なアイディアであり、[Flux](https://facebook.github.io/flux/docs/overview.html)、 [Redux](http://redux.js.org/) そして [The Elm Architecture](https://guide.elm-lang.org/architecture/)から影響を受けています。 他のパターンと異なるのは、Vuex は効率的な更新のために、Vue.js の粒度の細かいリアクティビティシステムを利用するよう特別に調整して実装されたライブラリだということです。 +あなたがもし対話型の方法でVuexを学びたいのであれば、[Scrimba](https://scrimba.com/g/gvuex)のVuexコースをぜひ試してみてください。 + ![vuex](/vuex.png) ### いつ、Vuexを使うべきでしょうか? diff --git a/docs/ja/guide/README.md b/docs/ja/guide/README.md index 7b7373280..d237dcc58 100644 --- a/docs/ja/guide/README.md +++ b/docs/ja/guide/README.md @@ -1,5 +1,7 @@ # Vuex 入門 + + Vuex アプリケーションの中心にあるものは**ストア**です。"ストア" は、基本的にアプリケーションの **状態(state)** を保持するコンテナです。単純なグローバルオブジェクトとの違いが 2つあります。 1. Vuex ストアはリアクティブです。Vue コンポーネントがストアから状態を取り出すとき、もしストアの状態が変化したら、ストアはリアクティブかつ効率的に更新を行います。 diff --git a/docs/ja/guide/actions.md b/docs/ja/guide/actions.md index a37242917..2439b42c5 100644 --- a/docs/ja/guide/actions.md +++ b/docs/ja/guide/actions.md @@ -1,5 +1,7 @@ # アクション + + アクションはミューテーションと似ていますが、下記の点で異なります: - アクションは、状態を変更するのではなく、ミューテーションをコミットします。 diff --git a/docs/ja/guide/forms.md b/docs/ja/guide/forms.md index 075f3d9fa..2ad1f8922 100644 --- a/docs/ja/guide/forms.md +++ b/docs/ja/guide/forms.md @@ -1,5 +1,7 @@ # フォームの扱い + + 厳格モードで Vuex を使用するとき、Vuex に属する状態の一部で `v-model` を使用するのは少しトリッキーです: ``` html diff --git a/docs/ja/guide/getters.md b/docs/ja/guide/getters.md index c016b647a..417ce71de 100644 --- a/docs/ja/guide/getters.md +++ b/docs/ja/guide/getters.md @@ -1,5 +1,7 @@ # ゲッター + + 例えば項目のリストをフィルタリングしたりカウントするときのように、ストアの状態を算出したいときがあります。 ``` js diff --git a/docs/ja/guide/modules.md b/docs/ja/guide/modules.md index e0c7794c5..c8fb33c25 100644 --- a/docs/ja/guide/modules.md +++ b/docs/ja/guide/modules.md @@ -1,5 +1,7 @@ # モジュール + + 単一ステートツリーを使うため、アプリケーションの全ての状態は、一つの大きなストアオブジェクトに内包されます。しかしながら、アプリケーションが大きくなるにつれて、ストアオブジェクトは膨れ上がってきます。 そのような場合に役立てるため Vuex ではストアを**モジュール**に分割できるようになっています。それぞれのモジュールは、モジュール自身の状態(state)、ミューテーション、アクション、ゲッター、モジュールさえも内包できます(モジュールをネストできます)- トップからボトムまでフラクタル構造です: diff --git a/docs/ja/guide/mutations.md b/docs/ja/guide/mutations.md index 967ce9db2..dfd4898e8 100644 --- a/docs/ja/guide/mutations.md +++ b/docs/ja/guide/mutations.md @@ -1,5 +1,7 @@ # ミューテーション + + 実際に Vuex のストアの状態を変更できる唯一の方法は、ミューテーションをコミットすることです。Vuex のミューテーションはイベントにとても近い概念です: 各ミューテーションは**タイプ**と**ハンドラ**を持ちます。ハンドラ関数は Vuex の状態(state)を第1引数として取得し、実際に状態の変更を行います: ``` js diff --git a/docs/ja/guide/plugins.md b/docs/ja/guide/plugins.md index 9ac7da452..7420c7236 100644 --- a/docs/ja/guide/plugins.md +++ b/docs/ja/guide/plugins.md @@ -1,5 +1,7 @@ # プラグイン + + Vuex ストア は、各ミューテーションへのフックを公開する `plugins` オプションを受け付けます。 Vuex プラグインは、単一の引数としてストアを受けつけるただの関数です: ``` js diff --git a/docs/ja/guide/state.md b/docs/ja/guide/state.md index c07a125b0..7141db0de 100644 --- a/docs/ja/guide/state.md +++ b/docs/ja/guide/state.md @@ -2,6 +2,8 @@ ### 単一ステートツリー + + Vuex は **単一ステートツリー (single state tree)** を使います。つまり、この単一なオブジェクトはアプリケーションレベルの状態が全て含まれており、"信頼できる唯一の情報源 (single source of truth)" として機能します。これは、通常、アプリケーションごとに1つしかストアは持たないことを意味します。単一ステートツリーは状態の特定の部分を見つけること、デバッグのために現在のアプリケーションの状態のスナップショットを撮ることを容易にします。 単一ステートツリーはモジュール性と競合しません。以降の章で、アプリケーションの状態とミューテーション(変更)をサブモジュールに分割する方法について説明します。 @@ -57,6 +59,8 @@ const Counter = { ### `mapState`  ヘルパー + + コンポーネントが複数のストアのステートプロパティやゲッターを必要としているとき、これらすべてにおいて、算出プロパティを宣言することは繰り返しで冗長です。これに対処するため、算出ゲッター関数を生成し、いくつかのキーストロークを省くのに役立つ `mapState` ヘルパーを使うことができます: ```js diff --git a/docs/ja/guide/testing.md b/docs/ja/guide/testing.md index 54a00d177..e3340ca20 100644 --- a/docs/ja/guide/testing.md +++ b/docs/ja/guide/testing.md @@ -1,5 +1,7 @@ # テスト + + 私たちが Vuex でユニットテストしたい主な部分はミューテーションとアクションです。 ### ミューテーションのテスト diff --git a/docs/kr/README.md b/docs/kr/README.md index 98730c268..87e2445fe 100644 --- a/docs/kr/README.md +++ b/docs/kr/README.md @@ -52,6 +52,8 @@ new Vue({ 이는 [Flux](https://facebook.github.io/flux/docs/overview.html), [Redux](http://redux.js.org/), [The Elm Architecture](https://guide.elm-lang.org/architecture/)에서 영감을 받은 Vuex의 기본 아이디어 입니다. 다른 패턴과 달리 Vuex는 Vue.js가 효율적인 업데이트를 위해 세분화된 반응 시스템을 활용하도록 특별히 고안된 라이브러리입니다. +대화식으로 Vuex를 배우고 싶다면 [Scrimba]((https://scrimba.com/g/gvuex))의 Vuex 과정에 등록하십시오. + ![vuex](/vuex.png) ### 언제 사용해야 하나요? diff --git a/docs/kr/guide/README.md b/docs/kr/guide/README.md index 4de68dc68..74cf732bc 100644 --- a/docs/kr/guide/README.md +++ b/docs/kr/guide/README.md @@ -1,5 +1,7 @@ # 시작하기 + + 모든 Vuex 애플리케이션의 중심에는 **store** 가 있습니다. "저장소"는 기본적으로 애플리케이션 **상태** 를 보유하고있는 컨테이너입니다. Vuex 저장소가 일반 전역 개체와 두 가지 다른 점이 있습니다. 1. Vuex store는 반응형 입니다. Vue 컴포넌트는 상태를 검색할 때 저장소의 상태가 변경되면 효율적으로 대응하고 업데이트합니다. diff --git a/docs/kr/guide/actions.md b/docs/kr/guide/actions.md index e36c24160..11dfcd215 100644 --- a/docs/kr/guide/actions.md +++ b/docs/kr/guide/actions.md @@ -1,5 +1,7 @@ # 액션 + + 액션은 변이와 유사합니다. 몇가지 다른 점은, - 상태를 변이시키는 대신 액션으로 변이에 대한 커밋을 합니다. diff --git a/docs/kr/guide/forms.md b/docs/kr/guide/forms.md index 03e7320c5..a332aa7ec 100644 --- a/docs/kr/guide/forms.md +++ b/docs/kr/guide/forms.md @@ -1,5 +1,7 @@ # 폼 핸들링 + + strict 모드로 Vuex를 사용하는 경우 Vuex에 포함된 부분에 `v-model`을 사용하는 것은 약간 까다로울 수 있습니다. ``` html diff --git a/docs/kr/guide/getters.md b/docs/kr/guide/getters.md index 0e42c5e1d..f38434f3e 100644 --- a/docs/kr/guide/getters.md +++ b/docs/kr/guide/getters.md @@ -1,5 +1,7 @@ # Getters + + 때로는 저장소 상태를 기반하는 상태를 계산해야 할 수도 있습니다.(예: 아이템 리스트를 필터링하고 계산) ``` js diff --git a/docs/kr/guide/modules.md b/docs/kr/guide/modules.md index 70a00267b..c2e1cd7ae 100644 --- a/docs/kr/guide/modules.md +++ b/docs/kr/guide/modules.md @@ -1,5 +1,7 @@ # 모듈 + + 단일 상태 트리를 사용하기 때문에 애플리케이션의 모든 상태가 하나의 큰 객체 안에 포함됩니다. 그러나 규모가 커짐에 따라 저장소는 매우 비대해질 수 있습니다. 이를 위해 Vuex는 저장소를 **모듈** 로 나눌 수 있습니다. 각 모듈은 자체 상태, 변이, 액션, 게터 및 심지어 중첩된 모듈을 포함 할 수 있습니다. diff --git a/docs/kr/guide/mutations.md b/docs/kr/guide/mutations.md index 6217890e4..1f7f0f156 100644 --- a/docs/kr/guide/mutations.md +++ b/docs/kr/guide/mutations.md @@ -1,5 +1,7 @@ # 변이 + + Vuex 저장소에서 실제로 상태를 변경하는 유일한 방법은 변이하는 것입니다. Vuex 변이는 이벤트와 매우 유사합니다. 각 변이에는 **타입** 문자열 **핸들러** 가 있습니다. 핸들러 함수는 실제 상태 수정을 하는 곳이며, 첫 번째 전달인자로 상태를받습니다. ``` js diff --git a/docs/kr/guide/plugins.md b/docs/kr/guide/plugins.md index 39c264d23..a90cd64a4 100644 --- a/docs/kr/guide/plugins.md +++ b/docs/kr/guide/plugins.md @@ -1,5 +1,7 @@ # 플러그인 + + Vuex 저장소는 각 변이에 대한 훅을 노출하는 `plugins` 옵션을 허용합니다. Vuex 플러그인은 저장소를 유일한 전달인자로 받는 함수입니다. ``` js diff --git a/docs/kr/guide/state.md b/docs/kr/guide/state.md index 4827b6bb0..5dc74f04e 100644 --- a/docs/kr/guide/state.md +++ b/docs/kr/guide/state.md @@ -2,6 +2,8 @@ ### 단일 상태 트리 + + Vuex는 **단일 상태 트리** 를 사용합니다. 즉, 이 단일 객체는 모든 애플리케이션 수준의 상태를 포함하며 "원본 소스" 역할을 합니다. 이는 각 애플리케이션마다 하나의 저장소만 갖게 된다는 것을 의미합니다. 단일 상태 트리를 사용하면 특정 상태를 쉽게 찾을 수 있으므로 디버깅을 위해 현재 앱 상태의 스냅 샷을 쉽게 가져올 수 있습니다. 단일 상태 트리는 모듈성과 충돌하지 않습니다. 나중에 상태와 변이를 하위 모듈로 분할하는 방법에 대해 설명합니다. @@ -58,6 +60,8 @@ const Counter = { ### `mapState` 헬퍼 + + 컴포넌트가 여러 저장소 상태 속성이나 getter를 사용해야하는 경우 계산된 속성을 모두 선언하면 반복적이고 장황해집니다. 이를 처리하기 위해 우리는 계산된 getter 함수를 생성하는 `mapState` 헬퍼를 사용하여 키 입력을 줄일 수 있습니다. ``` js diff --git a/docs/kr/guide/testing.md b/docs/kr/guide/testing.md index 27cc99fd6..64d9f5694 100644 --- a/docs/kr/guide/testing.md +++ b/docs/kr/guide/testing.md @@ -1,5 +1,7 @@ # 테스팅 + + Vuex에서 단위 테스트를 하고자 하는 주요 부분은 변이와 액션입니다. ### 변이 테스팅 diff --git a/docs/ptbr/README.md b/docs/ptbr/README.md index 32930a20b..f80f96de0 100644 --- a/docs/ptbr/README.md +++ b/docs/ptbr/README.md @@ -54,6 +54,8 @@ Além disso, definindo e separando os conceitos envolvidos no gerenciamento do e Esta é a ideia básica por trás do Vuex, inspirada por [Flux](https://facebook.github.io/flux/docs/overview.html), [Redux](http://redux.js.org/) e [The Elm Architecture](https://guide.elm-lang.org/architecture/). Ao contrário dos outros padrões, o Vuex também é uma implementação de biblioteca adaptada especificamente para o Vue.js tirar proveito de seu sistema de reatividade granular para atualizações eficientes. +Se você quiser aprender Vuex de um modo interativo, você pode conferir esse curso de [Vuex no Scrimba.](https://scrimba.com/g/gvuex) + ![vuex](/vuex.png) ### Quando usar o Vuex? diff --git a/docs/ptbr/guide/README.md b/docs/ptbr/guide/README.md index f9f56360a..388d93f02 100644 --- a/docs/ptbr/guide/README.md +++ b/docs/ptbr/guide/README.md @@ -1,5 +1,7 @@ # Começando + + No centro de cada aplicação Vuex existe o **_store_**. Um "_store_" é basicamente um recipiente que contém o **estado** da sua aplicação. Há duas coisas que tornam um _store_ Vuex diferente de um objeto global simples: 1. Os _stores_ Vuex são reativos. Quando os componentes do Vue obtêm o estado dele, eles atualizarão de forma reativa e eficiente se o estado do _store_ mudar. diff --git a/docs/ptbr/guide/actions.md b/docs/ptbr/guide/actions.md index 8a66eab85..506d4d84c 100644 --- a/docs/ptbr/guide/actions.md +++ b/docs/ptbr/guide/actions.md @@ -1,5 +1,7 @@ # Ações + + As ações são semelhantes às mutações, as diferenças são as seguintes: - Em vez de mudar o estado, as ações confirmam (ou fazem _commit_ de) mutações. diff --git a/docs/ptbr/guide/forms.md b/docs/ptbr/guide/forms.md index 0b1564324..14cd0d724 100644 --- a/docs/ptbr/guide/forms.md +++ b/docs/ptbr/guide/forms.md @@ -1,5 +1,7 @@ # Manipulação de Formulários + + Ao usar o Vuex no modo estrito, pode ser um pouco complicado usar `v-model` em um pedaço do estado que pertence ao Vuex: ``` html diff --git a/docs/ptbr/guide/getters.md b/docs/ptbr/guide/getters.md index b74b7f226..bc0922f4d 100644 --- a/docs/ptbr/guide/getters.md +++ b/docs/ptbr/guide/getters.md @@ -1,5 +1,7 @@ # Getters + + Às vezes, talvez precisemos calcular o estado derivado com base no estado do _store_, por exemplo, filtrar através de uma lista de itens e contá-los: ``` js diff --git a/docs/ptbr/guide/modules.md b/docs/ptbr/guide/modules.md index 54c3365f3..306c50c7f 100644 --- a/docs/ptbr/guide/modules.md +++ b/docs/ptbr/guide/modules.md @@ -1,5 +1,7 @@ # Módulos + + Devido ao uso de uma única árvore de estado, todo o estado de nossa aplicação está contido dentro de um grande objeto. No entanto, à medida que nosso aplicativo cresce em escala, o _store_ pode ficar realmente inchado. Para ajudar com isso, o Vuex nos permite dividir nosso _store_ em **módulos**. Cada módulo pode conter seu próprio estado, mutações, ações, _getters_ e até módulos aninhados - é todo o complexo caminho abaixo: diff --git a/docs/ptbr/guide/mutations.md b/docs/ptbr/guide/mutations.md index f2a5a5805..773f659ec 100644 --- a/docs/ptbr/guide/mutations.md +++ b/docs/ptbr/guide/mutations.md @@ -1,5 +1,7 @@ # Mutações + + A única maneira de realmente mudar de estado em um _store_ Vuex é por confirmar (ou fazer _commit_ de) uma mutação. As mutações do Vuex são muito semelhantes aos eventos: cada mutação tem uma cadeia de caracteres **tipo** e um **manipulador**. A função do manipulador é onde realizamos modificações de estado reais e ele receberá o estado como o 1º argumento: ``` js diff --git a/docs/ptbr/guide/plugins.md b/docs/ptbr/guide/plugins.md index 2e670a3ca..cc0f0fae4 100644 --- a/docs/ptbr/guide/plugins.md +++ b/docs/ptbr/guide/plugins.md @@ -1,5 +1,7 @@ # Plugins + + Os _stores_ do Vuex aceitam a opção _plugins_ que expõe _hooks_ para cada mutação. Um _plugin_ Vuex é simplesmente uma função que recebe um _store_ como seu único argumento: ``` js diff --git a/docs/ptbr/guide/state.md b/docs/ptbr/guide/state.md index 60a67750d..2f4ec24b3 100644 --- a/docs/ptbr/guide/state.md +++ b/docs/ptbr/guide/state.md @@ -2,6 +2,8 @@ ### Árvore Única de Estado + + O Vuex usa uma **árvore única de estado** - ou seja, esse único objeto contém todo o estado do seu nível de aplicação e serve como a "única fonte da verdade". Isso também significa que você terá apenas um _store_ para cada aplicativo. Uma árvore única de estado facilita a localização de uma parte específica do estado, e permite capturar facilmente momentos do estado atual do aplicativo para fins de depuração. A árvore única de estado não entra em conflito com a modularidade - em capítulos posteriores, discutiremos como dividir seu estado e mutações em sub-módulos. @@ -58,6 +60,8 @@ const Counter = { ### O Auxiliar `mapState` + + Quando um componente precisa fazer uso de várias propriedades do estado do _store_ ou _getters_, declarar todos esses dados computados pode ser repetitivo e verboso. Para lidar com isso, podemos usar o auxiliar `mapState` que gera funções _getter_ computadas para nós, economizando algumas linhas de código: ``` js diff --git a/docs/ptbr/guide/testing.md b/docs/ptbr/guide/testing.md index 38101e43e..ecffbcb0d 100644 --- a/docs/ptbr/guide/testing.md +++ b/docs/ptbr/guide/testing.md @@ -1,5 +1,7 @@ # Testando + + As partes principais que queremos testar no Vuex são mutações e ações. ### Testando Mutações diff --git a/docs/ru/README.md b/docs/ru/README.md index cdc6b6bdf..d8523f05b 100644 --- a/docs/ru/README.md +++ b/docs/ru/README.md @@ -54,6 +54,8 @@ new Vue({ Это основная идея Vuex, вдохновлённого [Flux](https://facebook.github.io/flux/docs/overview.html), [Redux](http://redux.js.org/) и [Архитектурой Elm](https://guide.elm-lang.org/architecture/). В отличие от других паттернов, Vuex реализован в виде библиотеки, специально предназначенной для Vue.js, чтобы использовать его систему реактивности для эффективного обновления. +Если хотите изучить Vuex в интерактивном режиме, попробуйте этот [курс по Vuex на Scrimba.](https://scrimba.com/g/gvuex) + ![vuex](/ru/vuex.png) ### Когда следует использовать Vuex? diff --git a/docs/ru/guide/README.md b/docs/ru/guide/README.md index 68a98df75..a20c0acad 100644 --- a/docs/ru/guide/README.md +++ b/docs/ru/guide/README.md @@ -1,5 +1,7 @@ # Введение + + В центре любого Vuex-приложения находится **хранилище**. «Хранилище» — это контейнер, в котором хранится **состояние** вашего приложения. Два момента отличают хранилище Vuex от простого глобального объекта: 1. Хранилище Vuex реактивно. Когда компоненты Vue полагаются на его состояние, то они будут реактивно и эффективно обновляться, если состояние хранилища изменяется. diff --git a/docs/ru/guide/actions.md b/docs/ru/guide/actions.md index 42d0c4460..511c5ca45 100644 --- a/docs/ru/guide/actions.md +++ b/docs/ru/guide/actions.md @@ -1,5 +1,7 @@ # Действия + + Действия — похожи на мутации с несколькими отличиями: * Вместо того, чтобы напрямую менять состояние, действия инициируют мутации; diff --git a/docs/ru/guide/forms.md b/docs/ru/guide/forms.md index 0658f2b96..239c16ef2 100644 --- a/docs/ru/guide/forms.md +++ b/docs/ru/guide/forms.md @@ -1,5 +1,7 @@ # Работа с формами + + При использовании строгого режима Vuex может показаться неочевидным как использовать `v-model` с частью состояния Vuex: ```html diff --git a/docs/ru/guide/getters.md b/docs/ru/guide/getters.md index 9c9d1daed..e0f126ef0 100644 --- a/docs/ru/guide/getters.md +++ b/docs/ru/guide/getters.md @@ -1,5 +1,7 @@ # Геттеры + + Иногда может потребоваться вычислять производное состояние на основе состояния хранилища, например, отфильтровать список и затем подсчитать количество элементов: ```js diff --git a/docs/ru/guide/modules.md b/docs/ru/guide/modules.md index f080afc5a..70187bcc3 100644 --- a/docs/ru/guide/modules.md +++ b/docs/ru/guide/modules.md @@ -1,5 +1,7 @@ # Модули + + Из-за использования единого дерева состояния, все глобальные данные приложения оказываются помещены в один большой объект. По мере роста приложения, хранилище может существенно раздуться. Чтобы помочь в этой беде, Vuex позволяет разделять хранилище на **модули**. Каждый модуль может содержать собственное состояние, мутации, действия, геттеры и даже встроенные подмодули — структура фрактальна: diff --git a/docs/ru/guide/mutations.md b/docs/ru/guide/mutations.md index 7b1530a15..81033830a 100644 --- a/docs/ru/guide/mutations.md +++ b/docs/ru/guide/mutations.md @@ -1,5 +1,7 @@ # Мутации + + Единственным способом изменения состояния хранилища во Vuex являются мутации. Мутации во Vuex очень похожи на события: каждая мутация имеет строковый **тип** и **функцию-обработчик**. В этом обработчике и происходят, собственно, изменения состояния, переданного в функцию первым аргументом: ```js diff --git a/docs/ru/guide/plugins.md b/docs/ru/guide/plugins.md index 03f1cce64..b52b18c81 100644 --- a/docs/ru/guide/plugins.md +++ b/docs/ru/guide/plugins.md @@ -1,5 +1,7 @@ # Плагины + + Хранилища Vuex принимают опцию `plugins`, предоставляющую хуки для каждой мутации. Vuex-плагин — это просто функция, получающая хранилище в качестве единственного параметра: ```js diff --git a/docs/ru/guide/state.md b/docs/ru/guide/state.md index 274a7995d..462d66457 100644 --- a/docs/ru/guide/state.md +++ b/docs/ru/guide/state.md @@ -2,6 +2,8 @@ ### Единое дерево состояния + + Vuex использует **единое дерево состояния** — когда один объект содержит всё глобальное состояние приложения и служит «единственным источником истины». Это также означает, что в приложении будет только одно такое хранилище. Единое дерево состояния позволяет легко найти нужную его часть или делать снимки текущего состояния приложения в целях отладки. Единое дерево состояния не противоречит модульности — в следующих главах мы изучим, как можно разделить состояние и мутации на под-модули. @@ -58,6 +60,8 @@ const Counter = { ### Вспомогательная функция `mapState` + + Когда компонент должен использовать множество свойств или геттеров хранилища, объявлять все эти вычисляемые свойства может быть утомительно. В таких случаях можно использовать функцию `mapState`, которая автоматически генерирует вычисляемые свойства: ```js diff --git a/docs/ru/guide/testing.md b/docs/ru/guide/testing.md index 616c16ac2..bd77ea655 100644 --- a/docs/ru/guide/testing.md +++ b/docs/ru/guide/testing.md @@ -1,5 +1,7 @@ # Тестирование + + В основном предметом модульного тестирования во Vuex являются мутации и действия. ### Тестирование мутаций diff --git a/docs/zh/README.md b/docs/zh/README.md index a58deffeb..8d2c11c4c 100644 --- a/docs/zh/README.md +++ b/docs/zh/README.md @@ -52,6 +52,8 @@ new Vue({ 这就是 Vuex 背后的基本思想,借鉴了 [Flux](https://facebook.github.io/flux/docs/overview.html)、[Redux](http://redux.js.org/) 和 [The Elm Architecture](https://guide.elm-lang.org/architecture/)。与其他模式不同的是,Vuex 是专门为 Vue.js 设计的状态管理库,以利用 Vue.js 的细粒度数据响应机制来进行高效的状态更新。 +如果你想要以交互式的方式学习Vuex,快来看看在[Scrimba](https://scrimba.com/g/gvuex)上的这门Vuex课程。 + ![vuex](/vuex.png) ### 什么情况下我应该使用 Vuex? diff --git a/docs/zh/guide/README.md b/docs/zh/guide/README.md index eab92199c..dfe4b7ae9 100644 --- a/docs/zh/guide/README.md +++ b/docs/zh/guide/README.md @@ -1,5 +1,7 @@ # 开始 + + 每一个 Vuex 应用的核心就是 store(仓库)。“store”基本上就是一个容器,它包含着你的应用中大部分的**状态 (state)**。Vuex 和单纯的全局对象有以下两点不同: 1. Vuex 的状态存储是响应式的。当 Vue 组件从 store 中读取状态的时候,若 store 中的状态发生变化,那么相应的组件也会相应地得到高效更新。 diff --git a/docs/zh/guide/actions.md b/docs/zh/guide/actions.md index d4ea1d8f2..a829af4d0 100644 --- a/docs/zh/guide/actions.md +++ b/docs/zh/guide/actions.md @@ -1,5 +1,7 @@ # Action + + Action 类似于 mutation,不同在于: - Action 提交的是 mutation,而不是直接变更状态。 diff --git a/docs/zh/guide/forms.md b/docs/zh/guide/forms.md index 99e7f041c..2d2dca19e 100644 --- a/docs/zh/guide/forms.md +++ b/docs/zh/guide/forms.md @@ -1,5 +1,7 @@ # 表单处理 + + 当在严格模式中使用 Vuex 时,在属于 Vuex 的 state 上使用 `v-model` 会比较棘手: ``` html diff --git a/docs/zh/guide/getters.md b/docs/zh/guide/getters.md index b8e2f729f..6cfe163d8 100644 --- a/docs/zh/guide/getters.md +++ b/docs/zh/guide/getters.md @@ -1,5 +1,7 @@ # Getter + + 有时候我们需要从 store 中的 state 中派生出一些状态,例如对列表进行过滤并计数: ``` js diff --git a/docs/zh/guide/modules.md b/docs/zh/guide/modules.md index c5a27fa4c..72950239f 100644 --- a/docs/zh/guide/modules.md +++ b/docs/zh/guide/modules.md @@ -1,5 +1,7 @@ # Module + + 由于使用单一状态树,应用的所有状态会集中到一个比较大的对象。当应用变得非常复杂时,store 对象就有可能变得相当臃肿。 为了解决以上问题,Vuex 允许我们将 store 分割成**模块(module)**。每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块——从上至下进行同样方式的分割: diff --git a/docs/zh/guide/mutations.md b/docs/zh/guide/mutations.md index 76e8be330..25dccb5ac 100644 --- a/docs/zh/guide/mutations.md +++ b/docs/zh/guide/mutations.md @@ -1,5 +1,7 @@ # Mutation + + 更改 Vuex 的 store 中的状态的唯一方法是提交 mutation。Vuex 中的 mutation 非常类似于事件:每个 mutation 都有一个字符串的 **事件类型 (type)** 和 一个 **回调函数 (handler)**。这个回调函数就是我们实际进行状态更改的地方,并且它会接受 state 作为第一个参数: ``` js diff --git a/docs/zh/guide/plugins.md b/docs/zh/guide/plugins.md index 92c157c9c..a68134ec6 100644 --- a/docs/zh/guide/plugins.md +++ b/docs/zh/guide/plugins.md @@ -1,5 +1,7 @@ # 插件 + + Vuex 的 store 接受 `plugins` 选项,这个选项暴露出每次 mutation 的钩子。Vuex 插件就是一个函数,它接收 store 作为唯一参数: ``` js diff --git a/docs/zh/guide/state.md b/docs/zh/guide/state.md index 892773abb..40993b863 100644 --- a/docs/zh/guide/state.md +++ b/docs/zh/guide/state.md @@ -2,6 +2,8 @@ ### 单一状态树 + + Vuex 使用**单一状态树**——是的,用一个对象就包含了全部的应用层级状态。至此它便作为一个“唯一数据源 ([SSOT](https://en.wikipedia.org/wiki/Single_source_of_truth))”而存在。这也意味着,每个应用将仅仅包含一个 store 实例。单一状态树让我们能够直接地定位任一特定的状态片段,在调试的过程中也能轻易地取得整个当前应用状态的快照。 单状态树和模块化并不冲突——在后面的章节里我们会讨论如何将状态和状态变更事件分布到各个子模块中。 @@ -57,6 +59,8 @@ const Counter = { ### `mapState` 辅助函数 + + 当一个组件需要获取多个状态时候,将这些状态都声明为计算属性会有些重复和冗余。为了解决这个问题,我们可以使用 `mapState` 辅助函数帮助我们生成计算属性,让你少按几次键: ``` js diff --git a/docs/zh/guide/testing.md b/docs/zh/guide/testing.md index b2cbc4579..ce511abba 100644 --- a/docs/zh/guide/testing.md +++ b/docs/zh/guide/testing.md @@ -1,5 +1,7 @@ # 测试 + + 我们主要想针对 Vuex 中的 mutation 和 action 进行单元测试。 ### 测试 Mutation From e262c3676d556db27788645b00e3e22c1dadb5b7 Mon Sep 17 00:00:00 2001 From: Jenny_L Date: Fri, 8 Mar 2019 02:10:46 +0800 Subject: [PATCH 15/29] doc: change ECMASCript into ECMAScript (#1514) --- docs/fr/guide/state.md | 2 +- docs/zh/guide/state.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/fr/guide/state.md b/docs/fr/guide/state.md index 63ea28263..84ad0f44e 100644 --- a/docs/fr/guide/state.md +++ b/docs/fr/guide/state.md @@ -96,7 +96,7 @@ computed: mapState([ ### Opérateur de décomposition -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://github.com/sebmarkbage/ecmascript-rest-spread) (qui est une proposition stage-4 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://github.com/sebmarkbage/ecmascript-rest-spread) (qui est une proposition stage-4 ECMAScript), nous pouvons grandement simplifier la syntaxe : ``` js computed: { diff --git a/docs/zh/guide/state.md b/docs/zh/guide/state.md index 40993b863..1d543ae54 100644 --- a/docs/zh/guide/state.md +++ b/docs/zh/guide/state.md @@ -95,7 +95,7 @@ computed: mapState([ ### 对象展开运算符 -`mapState` 函数返回的是一个对象。我们如何将它与局部计算属性混合使用呢?通常,我们需要使用一个工具函数将多个对象合并为一个,以使我们可以将最终对象传给 `computed` 属性。但是自从有了[对象展开运算符](https://github.com/sebmarkbage/ecmascript-rest-spread)(现处于 ECMASCript 提案 stage-4 阶段),我们可以极大地简化写法: +`mapState` 函数返回的是一个对象。我们如何将它与局部计算属性混合使用呢?通常,我们需要使用一个工具函数将多个对象合并为一个,以使我们可以将最终对象传给 `computed` 属性。但是自从有了[对象展开运算符](https://github.com/sebmarkbage/ecmascript-rest-spread)(现处于 ECMAScript 提案 stage-4 阶段),我们可以极大地简化写法: ``` js computed: { From 0e109e2a38dafdc0c2bd6bd3892bc66cfe252b16 Mon Sep 17 00:00:00 2001 From: David Sandoz Date: Sun, 10 Mar 2019 14:44:15 +0100 Subject: [PATCH 16/29] fix(types): Make mutation and action payload optional in definition file (#1517) * Make mutation payload optional in definition file When testing a mutation without payload in TypeScript, it complains that about the missing payload, even though it's not mandatory. This PR simply makes the payload optional. Fixes #1491 * Make action payload optional in definition file --- types/index.d.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/types/index.d.ts b/types/index.d.ts index 46316bb2a..3cd40067a 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -97,7 +97,7 @@ export interface StoreOptions { strict?: boolean; } -export type ActionHandler = (this: Store, injectee: ActionContext, payload: any) => any; +export type ActionHandler = (this: Store, injectee: ActionContext, payload?: any) => any; export interface ActionObject { root?: boolean; handler: ActionHandler; @@ -105,7 +105,7 @@ export interface ActionObject { export type Getter = (state: S, getters: any, rootState: R, rootGetters: any) => any; export type Action = ActionHandler | ActionObject; -export type Mutation = (state: S, payload: any) => any; +export type Mutation = (state: S, payload?: any) => any; export type Plugin = (store: Store) => any; export interface Module { From 1ff6a24db9c619f6736c921df60e13127cf9ddae Mon Sep 17 00:00:00 2001 From: dollinad <39140769+dollinad@users.noreply.github.com> Date: Sat, 16 Mar 2019 14:06:21 -0700 Subject: [PATCH 17/29] Fix minor errors in README.md Changes involve: - Removal of dead links: data flow.png and vuex.png - Removal of discourse markers (although, also, in addition) to make sentences precise --- docs/README.md | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/docs/README.md b/docs/README.md index 67283092e..233d530c2 100644 --- a/docs/README.md +++ b/docs/README.md @@ -31,17 +31,13 @@ new Vue({ It is a self-contained app with the following parts: -- The **state**, which is the source of truth that drives our app; -- The **view**, which is just a declarative mapping of the **state**; -- The **actions**, which are the possible ways the state could change in reaction to user inputs from the **view**. +- The **state**, the source of truth that drives our app; +- The **view**, a declarative mapping of the **state**; +- The **actions**, the possible ways the state could change in reaction to user inputs from the **view**. -This is an extremely simple representation of the concept of "one-way data flow": +This is an simple representation of the concept of "one-way data flow": -

- -

- -However, the simplicity quickly breaks down when we have **multiple components that share common state**: +However, the simplicity quickly breaks down when we have **multiple components that share a common state**: - Multiple views may depend on the same piece of state. - Actions from different views may need to mutate the same piece of state. @@ -50,17 +46,15 @@ For problem one, passing props can be tedious for deeply nested components, and So why don't we extract the shared state out of the components, and manage it in a global singleton? With this, our component tree becomes a big "view", and any component can access the state or trigger actions, no matter where they are in the tree! -In addition, by defining and separating the concepts involved in state management and enforcing certain rules, we also give our code more structure and maintainability. +By defining and separating the concepts involved in state management and enforcing rules that maintain independece between views and states, we give our code more structure and maintainability. This is the basic idea behind Vuex, inspired by [Flux](https://facebook.github.io/flux/docs/overview.html), [Redux](http://redux.js.org/) and [The Elm Architecture](https://guide.elm-lang.org/architecture/). Unlike the other patterns, Vuex is also a library implementation tailored specifically for Vue.js to take advantage of its granular reactivity system for efficient updates. If you want to learn Vuex in an interactive way you can check out this [Vuex course on Scrimba](https://scrimba.com/g/gvuex), which gives you a mix of screencast and code playground that you can pause and play around with anytime. -![vuex](/vuex.png) - ### When Should I Use It? -Although Vuex helps us deal with shared state management, it also comes with the cost of more concepts and boilerplate. It's a trade-off between short term and long term productivity. +Vuex helps us deal with shared state management with the cost of more concepts and boilerplate. It's a trade-off between short term and long term productivity. If you've never built a large-scale SPA and jump right into Vuex, it may feel verbose and daunting. That's perfectly normal - if your app is simple, you will most likely be fine without Vuex. A simple [store pattern](https://vuejs.org/v2/guide/state-management.html#Simple-State-Management-from-Scratch) may be all you need. But if you are building a medium-to-large-scale SPA, chances are you have run into situations that make you think about how to better handle state outside of your Vue components, and Vuex will be the natural next step for you. There's a good quote from Dan Abramov, the author of Redux: From d1b2cb79743696b739f2f4591366baa5eaf73540 Mon Sep 17 00:00:00 2001 From: dollinad <39140769+dollinad@users.noreply.github.com> Date: Sat, 16 Mar 2019 19:10:45 -0700 Subject: [PATCH 18/29] Updated Edits Re-added link for Vuex --- docs/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/README.md b/docs/README.md index 233d530c2..4cdd5c891 100644 --- a/docs/README.md +++ b/docs/README.md @@ -54,7 +54,7 @@ If you want to learn Vuex in an interactive way you can check out this [Vuex cou ### When Should I Use It? -Vuex helps us deal with shared state management with the cost of more concepts and boilerplate. It's a trade-off between short term and long term productivity. +[Vuex](https://vuex.vuejs.org/) helps us deal with shared state management with the cost of more concepts and boilerplate. It's a trade-off between short term and long term productivity. If you've never built a large-scale SPA and jump right into Vuex, it may feel verbose and daunting. That's perfectly normal - if your app is simple, you will most likely be fine without Vuex. A simple [store pattern](https://vuejs.org/v2/guide/state-management.html#Simple-State-Management-from-Scratch) may be all you need. But if you are building a medium-to-large-scale SPA, chances are you have run into situations that make you think about how to better handle state outside of your Vue components, and Vuex will be the natural next step for you. There's a good quote from Dan Abramov, the author of Redux: From d0727249442334f2e3a84431f651688bc24c8e41 Mon Sep 17 00:00:00 2001 From: dollinad <39140769+dollinad@users.noreply.github.com> Date: Sat, 16 Mar 2019 19:28:08 -0700 Subject: [PATCH 19/29] Update edits1 Readded flow.png and veux.png --- docs/README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/README.md b/docs/README.md index 4cdd5c891..1e1365760 100644 --- a/docs/README.md +++ b/docs/README.md @@ -37,6 +37,10 @@ It is a self-contained app with the following parts: This is an simple representation of the concept of "one-way data flow": +

+ +

+ However, the simplicity quickly breaks down when we have **multiple components that share a common state**: - Multiple views may depend on the same piece of state. @@ -48,6 +52,8 @@ So why don't we extract the shared state out of the components, and manage it in By defining and separating the concepts involved in state management and enforcing rules that maintain independece between views and states, we give our code more structure and maintainability. +![vuex](/vuex.png) + This is the basic idea behind Vuex, inspired by [Flux](https://facebook.github.io/flux/docs/overview.html), [Redux](http://redux.js.org/) and [The Elm Architecture](https://guide.elm-lang.org/architecture/). Unlike the other patterns, Vuex is also a library implementation tailored specifically for Vue.js to take advantage of its granular reactivity system for efficient updates. If you want to learn Vuex in an interactive way you can check out this [Vuex course on Scrimba](https://scrimba.com/g/gvuex), which gives you a mix of screencast and code playground that you can pause and play around with anytime. From 683579c1c7b699e69dee063b935ef4e7ca7453f8 Mon Sep 17 00:00:00 2001 From: ktsn Date: Sun, 17 Mar 2019 12:40:47 +0800 Subject: [PATCH 20/29] docs: tweaks --- docs/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/README.md b/docs/README.md index 1e1365760..905874b95 100644 --- a/docs/README.md +++ b/docs/README.md @@ -52,15 +52,15 @@ So why don't we extract the shared state out of the components, and manage it in By defining and separating the concepts involved in state management and enforcing rules that maintain independece between views and states, we give our code more structure and maintainability. -![vuex](/vuex.png) - This is the basic idea behind Vuex, inspired by [Flux](https://facebook.github.io/flux/docs/overview.html), [Redux](http://redux.js.org/) and [The Elm Architecture](https://guide.elm-lang.org/architecture/). Unlike the other patterns, Vuex is also a library implementation tailored specifically for Vue.js to take advantage of its granular reactivity system for efficient updates. If you want to learn Vuex in an interactive way you can check out this [Vuex course on Scrimba](https://scrimba.com/g/gvuex), which gives you a mix of screencast and code playground that you can pause and play around with anytime. +![vuex](/vuex.png) + ### When Should I Use It? -[Vuex](https://vuex.vuejs.org/) helps us deal with shared state management with the cost of more concepts and boilerplate. It's a trade-off between short term and long term productivity. +Vuex helps us deal with shared state management with the cost of more concepts and boilerplate. It's a trade-off between short term and long term productivity. If you've never built a large-scale SPA and jump right into Vuex, it may feel verbose and daunting. That's perfectly normal - if your app is simple, you will most likely be fine without Vuex. A simple [store pattern](https://vuejs.org/v2/guide/state-management.html#Simple-State-Management-from-Scratch) may be all you need. But if you are building a medium-to-large-scale SPA, chances are you have run into situations that make you think about how to better handle state outside of your Vue components, and Vuex will be the natural next step for you. There's a good quote from Dan Abramov, the author of Redux: From 120cec0a1036145b67bc08bdb9839b705ea44ba6 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Tue, 19 Mar 2019 08:39:43 -0500 Subject: [PATCH 21/29] Rephrase dumb to silly (#1525) Replace dumb with silly, since dumb means mute or unable to speak. What the document means here is that this function call may seem to be a bit extra and non obvious at first glance. The whimsical word "silly" is a nice stand in for this. --- docs/guide/actions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/guide/actions.md b/docs/guide/actions.md index 7bf4fc933..081141ab8 100644 --- a/docs/guide/actions.md +++ b/docs/guide/actions.md @@ -47,7 +47,7 @@ Actions are triggered with the `store.dispatch` method: store.dispatch('increment') ``` -This may look dumb at first sight: if we want to increment the count, why don't we just call `store.commit('increment')` directly? Remember that **mutations have to be synchronous**? Actions don't. We can perform **asynchronous** operations inside an action: +This may look silly at first sight: if we want to increment the count, why don't we just call `store.commit('increment')` directly? Remember that **mutations have to be synchronous**? Actions don't. We can perform **asynchronous** operations inside an action: ``` js actions: { From b58d3d6a6426e901175a04bf6dcf206561cc82f5 Mon Sep 17 00:00:00 2001 From: Styx <1654630248@qq.com> Date: Tue, 19 Mar 2019 21:40:45 +0800 Subject: [PATCH 22/29] docs: fixed a sentence into bold (#1524) --- docs/zh/guide/strict.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/zh/guide/strict.md b/docs/zh/guide/strict.md index ad71ce59f..38d856aad 100644 --- a/docs/zh/guide/strict.md +++ b/docs/zh/guide/strict.md @@ -13,7 +13,7 @@ const store = new Vuex.Store({ ### 开发环境与发布环境 -**不要在发布环境下启用严格模式!**严格模式会深度监测状态树来检测不合规的状态变更——请确保在发布环境下关闭严格模式,以避免性能损失。 +**不要在发布环境下启用严格模式!** 严格模式会深度监测状态树来检测不合规的状态变更——请确保在发布环境下关闭严格模式,以避免性能损失。 类似于插件,我们可以让构建工具来处理这种情况: From cb9986ae5a62e002a1d876e881ee5f31dd410888 Mon Sep 17 00:00:00 2001 From: Parth Date: Mon, 25 Mar 2019 18:01:53 +0530 Subject: [PATCH 23/29] =?UTF-8?q?fix:=20Memory=20leak=20happening=20while?= =?UTF-8?q?=20using=20registerModule/u=E2=80=A6=20(#1508)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Fixed issue#1507 : Memory leak happening while using registerModule/unregisterModule. * Adding comment for leak description. Simplyfy partial function to take only one argument. * Removed oldVm.computed = null. This statement is not required --- src/store.js | 6 ++++-- src/util.js | 6 ++++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/store.js b/src/store.js index dfcc755f8..a79252b50 100644 --- a/src/store.js +++ b/src/store.js @@ -1,7 +1,7 @@ import applyMixin from './mixin' import devtoolPlugin from './plugins/devtool' import ModuleCollection from './module/module-collection' -import { forEachValue, isObject, isPromise, assert } from './util' +import { forEachValue, isObject, isPromise, assert, partial } from './util' let Vue // bind on install @@ -256,7 +256,9 @@ function resetStoreVM (store, state, hot) { const computed = {} forEachValue(wrappedGetters, (fn, key) => { // use computed to leverage its lazy-caching mechanism - computed[key] = () => fn(store) + // direct inline function use will lead to closure preserving oldVm. + // using partial to return function with only arguments preserved in closure enviroment. + computed[key] = partial(fn, store) Object.defineProperty(store.getters, key, { get: () => store._vm[key], enumerable: true // for local getters diff --git a/src/util.js b/src/util.js index fb1203251..2df74bb16 100644 --- a/src/util.js +++ b/src/util.js @@ -64,3 +64,9 @@ export function isPromise (val) { export function assert (condition, msg) { if (!condition) throw new Error(`[vuex] ${msg}`) } + +export function partial (fn, arg) { + return function () { + return fn(arg) + } +} From 0b1ceeca760bb6a376ea71426934306a88d046c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8B=BE=E4=B8=89=E8=82=A1=E5=9B=9B?= Date: Mon, 25 Mar 2019 20:44:05 +0800 Subject: [PATCH 24/29] docs(zh): updated (#1529) * docs(zh): updated * Update strict.md --- docs/zh/README.md | 8 ++++---- docs/zh/guide/strict.md | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/zh/README.md b/docs/zh/README.md index 8d2c11c4c..a4e55325d 100644 --- a/docs/zh/README.md +++ b/docs/zh/README.md @@ -33,7 +33,7 @@ new Vue({ - **view**,以声明方式将 **state** 映射到视图; - **actions**,响应在 **view** 上的用户输入导致的状态变化。 -以下是一个表示“单向数据流”理念的极简示意: +以下是一个表示“单向数据流”理念的简单示意:

@@ -48,17 +48,17 @@ new Vue({ 因此,我们为什么不把组件的共享状态抽取出来,以一个全局单例模式管理呢?在这种模式下,我们的组件树构成了一个巨大的“视图”,不管在树的哪个位置,任何组件都能获取状态或者触发行为! -另外,通过定义和隔离状态管理中的各种概念并强制遵守一定的规则,我们的代码将会变得更结构化且易维护。 +通过定义和隔离状态管理中的各种概念并通过强制规则维持视图和状态间的独立性,我们的代码将会变得更结构化且易维护。 这就是 Vuex 背后的基本思想,借鉴了 [Flux](https://facebook.github.io/flux/docs/overview.html)、[Redux](http://redux.js.org/) 和 [The Elm Architecture](https://guide.elm-lang.org/architecture/)。与其他模式不同的是,Vuex 是专门为 Vue.js 设计的状态管理库,以利用 Vue.js 的细粒度数据响应机制来进行高效的状态更新。 -如果你想要以交互式的方式学习Vuex,快来看看在[Scrimba](https://scrimba.com/g/gvuex)上的这门Vuex课程。 +如果你想交互式地学习 Vuex,可以看这个 [Scrimba 上的 Vuex 课程](https://scrimba.com/g/gvuex),它将录屏和代码试验场混合在了一起,你可以随时暂停并尝试。 ![vuex](/vuex.png) ### 什么情况下我应该使用 Vuex? -虽然 Vuex 可以帮助我们管理共享状态,但也附带了更多的概念和框架。这需要对短期和长期效益进行权衡。 +Vuex 可以帮助我们管理共享状态,并附带了更多的概念和框架。这需要对短期和长期效益进行权衡。 如果您不打算开发大型单页应用,使用 Vuex 可能是繁琐冗余的。确实是如此——如果您的应用够简单,您最好不要使用 Vuex。一个简单的 [store 模式](https://cn.vuejs.org/v2/guide/state-management.html#简单状态管理起步使用)就足够您所需了。但是,如果您需要构建一个中大型单页应用,您很可能会考虑如何更好地在组件外部管理状态,Vuex 将会成为自然而然的选择。引用 Redux 的作者 Dan Abramov 的话说就是: diff --git a/docs/zh/guide/strict.md b/docs/zh/guide/strict.md index 38d856aad..fc6175b8e 100644 --- a/docs/zh/guide/strict.md +++ b/docs/zh/guide/strict.md @@ -13,7 +13,7 @@ const store = new Vuex.Store({ ### 开发环境与发布环境 -**不要在发布环境下启用严格模式!** 严格模式会深度监测状态树来检测不合规的状态变更——请确保在发布环境下关闭严格模式,以避免性能损失。 +**不要在发布环境下启用严格模式**!严格模式会深度监测状态树来检测不合规的状态变更——请确保在发布环境下关闭严格模式,以避免性能损失。 类似于插件,我们可以让构建工具来处理这种情况: From 13dc501587bca080b399ff3594146ccdcecadbe1 Mon Sep 17 00:00:00 2001 From: tomouchi Date: Mon, 25 Mar 2019 21:45:47 +0900 Subject: [PATCH 25/29] docs(ja): tweak code example (#1528) --- docs/ja/guide/hot-reload.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/ja/guide/hot-reload.md b/docs/ja/guide/hot-reload.md index 8283537fd..8024f77f7 100644 --- a/docs/ja/guide/hot-reload.md +++ b/docs/ja/guide/hot-reload.md @@ -28,8 +28,8 @@ if (module.hot) { module.hot.accept(['./mutations', './modules/a'], () => { // 更新されたモジュールをインポートする // babel 6 のモジュール出力のため、ここでは .default を追加しなければならない - const newActions = require('./actions').default const newMutations = require('./mutations').default + const newModuleA = require('./modules/a').default // 新しいモジュールとミューテーションにスワップ store.hotUpdate({ mutations: newMutations, From 3f87e0ad9dd82eeaa757b59b79f5ed3011008f92 Mon Sep 17 00:00:00 2001 From: Bruno Soares Nepomuceno Date: Mon, 25 Mar 2019 09:47:59 -0300 Subject: [PATCH 26/29] =?UTF-8?q?docs(pt-br):=20Corre=C3=A7=C3=A3o=20de=20?= =?UTF-8?q?erro=20de=20digita=C3=A7=C3=A3o=20(#1527)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Mudança de "argumetos" para "argumentos" --- docs-gitbook/pt-br/getting-started.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs-gitbook/pt-br/getting-started.md b/docs-gitbook/pt-br/getting-started.md index 161937f78..8b3917833 100644 --- a/docs-gitbook/pt-br/getting-started.md +++ b/docs-gitbook/pt-br/getting-started.md @@ -34,7 +34,7 @@ store.commit('increment') console.log(store.state.count) // -> 1 ``` -Novamente, a razão pela qual estamos fazendo _commit_ de uma mutação em vez de mudar `store.state.count` diretamente, é porque queremos rastreá-la explicitamente. Esta convenção simples torna sua intenção mais explícita, de modo que você possa ter melhores argumetos sobre as mudanças de estado em seu aplicativo ao ler o código. Além disso, isso nos dá a oportunidade de implementar ferramentas que podem registrar cada mutação, tirar _snapshots_ de estado ou mesmo realizar depuração viajando pelo histórico de estado (_time travel_). +Novamente, a razão pela qual estamos fazendo _commit_ de uma mutação em vez de mudar `store.state.count` diretamente, é porque queremos rastreá-la explicitamente. Esta convenção simples torna sua intenção mais explícita, de modo que você possa ter melhores argumentos sobre as mudanças de estado em seu aplicativo ao ler o código. Além disso, isso nos dá a oportunidade de implementar ferramentas que podem registrar cada mutação, tirar _snapshots_ de estado ou mesmo realizar depuração viajando pelo histórico de estado (_time travel_). Usar o estado do _store_ em um componente simplesmente envolve o retorno do estado dentro de um dado computado, porque o estado do _store_ é reativo. Fazer alterações simplesmente significa fazer _commit_ de mutações nos métodos dos componentes. From d7c7f9844831f98c5c9aaca213746c4ccc5d6929 Mon Sep 17 00:00:00 2001 From: ziga Date: Wed, 10 Apr 2019 21:48:36 -0400 Subject: [PATCH 27/29] feat(esm build): build ES modules for browser (#1533) --- build/build.main.js | 17 ++++++++++------- build/configs.js | 21 +++++++++++++++++++-- package.json | 2 +- yarn.lock | 24 +++++++++++++++++++++++- 4 files changed, 53 insertions(+), 11 deletions(-) diff --git a/build/build.main.js b/build/build.main.js index bfd68446e..7f6e4e7ec 100644 --- a/build/build.main.js +++ b/build/build.main.js @@ -1,7 +1,7 @@ const fs = require('fs') const path = require('path') const zlib = require('zlib') -const uglify = require('uglify-js') +const terser = require('terser') const rollup = require('rollup') const configs = require('./configs') @@ -27,21 +27,24 @@ function build (builds) { } function buildEntry ({ input, output }) { - const isProd = /min\.js$/.test(output.file) + const { file, banner } = output + const isProd = /min\.js$/.test(file) return rollup.rollup(input) .then(bundle => bundle.generate(output)) .then(({ output: [{ code }] }) => { if (isProd) { - var minified = (output.banner ? output.banner + '\n' : '') + uglify.minify(code, { + const minified = (banner ? banner + '\n' : '') + terser.minify(code, { + toplevel: true, output: { - /* eslint-disable camelcase */ ascii_only: true - /* eslint-enable camelcase */ + }, + compress: { + pure_funcs: ['makeMap'] } }).code - return write(output.file, minified, true) + return write(file, minified, true) } else { - return write(output.file, code) + return write(file, code) } }) } diff --git a/build/configs.js b/build/configs.js index ebabe32ab..54c5f27df 100644 --- a/build/configs.js +++ b/build/configs.js @@ -33,6 +33,20 @@ const configs = { input: resolve('src/index.esm.js'), file: resolve('dist/vuex.esm.js'), format: 'es' + }, + 'esm-browser-dev': { + input: resolve('src/index.esm.js'), + file: resolve('dist/vuex.esm.browser.js'), + format: 'es', + env: 'development', + transpile: false + }, + 'esm-browser-prod': { + input: resolve('src/index.esm.js'), + file: resolve('dist/vuex.esm.browser.min.js'), + format: 'es', + env: 'production', + transpile: false } } @@ -43,8 +57,7 @@ function genConfig (opts) { plugins: [ replace({ __VERSION__: version - }), - buble() + }) ] }, output: { @@ -61,6 +74,10 @@ function genConfig (opts) { })) } + if (opts.transpile !== false) { + config.input.plugins.push(buble()) + } + return config } diff --git a/package.json b/package.json index 375ada242..675e1ee36 100644 --- a/package.json +++ b/package.json @@ -61,9 +61,9 @@ "rollup-plugin-buble": "^0.19.6", "rollup-plugin-replace": "^2.1.0", "selenium-server": "^2.53.1", + "terser": "^3.17.0", "todomvc-app-css": "^2.1.0", "typescript": "^3.2.2", - "uglify-js": "^3.1.2", "vue": "^2.5.22", "vue-loader": "^15.2.1", "vue-template-compiler": "^2.5.22", diff --git a/yarn.lock b/yarn.lock index 4602ea812..0871218f6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2729,6 +2729,11 @@ commander@^2.15.1: resolved "https://registry.yarnpkg.com/commander/-/commander-2.19.0.tgz#f6198aa84e5b83c46054b94ddedbfed5ee9ff12a" integrity sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg== +commander@^2.19.0: + version "2.20.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.0.tgz#d58bb2b5c1ee8f87b0d340027e9e94e222c5a422" + integrity sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ== + common-tags@^1.4.0: version "1.8.0" resolved "https://registry.yarnpkg.com/common-tags/-/common-tags-1.8.0.tgz#8e3153e542d4a39e9b10554434afaaf98956a937" @@ -8406,6 +8411,14 @@ source-map-support@^0.4.15: dependencies: source-map "^0.5.6" +source-map-support@~0.5.10: + version "0.5.12" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.12.tgz#b4f3b10d51857a5af0138d3ce8003b201613d599" + integrity sha512-4h2Pbvyy15EE02G+JOZpUCmqWJuqrs+sEkzewTm++BPi7Hvn/HwcqLAcNxYAyI0x13CpPPn+kMjl+hplXMHITQ== + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + source-map-support@~0.5.6: version "0.5.10" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.10.tgz#2214080bc9d51832511ee2bab96e3c2f9353120c" @@ -8825,6 +8838,15 @@ terser-webpack-plugin@^1.1.0: webpack-sources "^1.1.0" worker-farm "^1.5.2" +terser@^3.17.0: + version "3.17.0" + resolved "https://registry.yarnpkg.com/terser/-/terser-3.17.0.tgz#f88ffbeda0deb5637f9d24b0da66f4e15ab10cb2" + integrity sha512-/FQzzPJmCpjAH9Xvk2paiWrFq+5M6aVOf+2KRbwhByISDX/EujxsK+BAvrhb6H+2rtrLCHK9N01wO014vrIwVQ== + dependencies: + commander "^2.19.0" + source-map "~0.6.1" + source-map-support "~0.5.10" + terser@^3.8.1: version "3.14.1" resolved "https://registry.yarnpkg.com/terser/-/terser-3.14.1.tgz#cc4764014af570bc79c79742358bd46926018a32" @@ -9057,7 +9079,7 @@ uc.micro@^1.0.1, uc.micro@^1.0.5: resolved "https://registry.yarnpkg.com/uc.micro/-/uc.micro-1.0.5.tgz#0c65f15f815aa08b560a61ce8b4db7ffc3f45376" integrity sha512-JoLI4g5zv5qNyT09f4YAvEZIIV1oOjqnewYg5D38dkQljIzpPT296dbIGvKro3digYI1bkb7W6EP1y4uDlmzLg== -uglify-js@3.4.x, uglify-js@^3.1.2: +uglify-js@3.4.x: version "3.4.9" resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.4.9.tgz#af02f180c1207d76432e473ed24a28f4a782bae3" integrity sha512-8CJsbKOtEbnJsTyv6LE6m6ZKniqMiFWmm9sRbopbkGs3gMPPfd3Fh8iIA4Ykv5MgaTbqHr4BaoGLJLZNhsrW1Q== From cf090632f03d7fb88e456c4d37b1316650599aca Mon Sep 17 00:00:00 2001 From: Guillaume Chau Date: Wed, 8 May 2019 23:24:12 +0200 Subject: [PATCH 28/29] [build] 3.1.1 --- dist/vuex.common.js | 23 +- dist/vuex.esm.browser.js | 969 +++++++++++++++++++++++++++++++++++ dist/vuex.esm.browser.min.js | 6 + dist/vuex.esm.js | 23 +- dist/vuex.js | 23 +- dist/vuex.min.js | 4 +- 6 files changed, 1028 insertions(+), 20 deletions(-) create mode 100644 dist/vuex.esm.browser.js create mode 100644 dist/vuex.esm.browser.min.js diff --git a/dist/vuex.common.js b/dist/vuex.common.js index 88436c580..28e5f9450 100644 --- a/dist/vuex.common.js +++ b/dist/vuex.common.js @@ -1,5 +1,5 @@ /** - * vuex v3.1.0 + * vuex v3.1.1 * (c) 2019 Evan You * @license MIT */ @@ -41,9 +41,12 @@ function applyMixin (Vue) { } } -var devtoolHook = - typeof window !== 'undefined' && - window.__VUE_DEVTOOLS_GLOBAL_HOOK__; +var target = typeof window !== 'undefined' + ? window + : typeof global !== 'undefined' + ? global + : {}; +var devtoolHook = target.__VUE_DEVTOOLS_GLOBAL_HOOK__; function devtoolPlugin (store) { if (!devtoolHook) { return } @@ -89,6 +92,12 @@ function assert (condition, msg) { if (!condition) { throw new Error(("[vuex] " + msg)) } } +function partial (fn, arg) { + return function () { + return fn(arg) + } +} + // Base data struct for store's module, package with some attribute and method var Module = function Module (rawModule, runtime) { this.runtime = runtime; @@ -550,7 +559,9 @@ function resetStoreVM (store, state, hot) { var computed = {}; forEachValue(wrappedGetters, function (fn, key) { // use computed to leverage its lazy-caching mechanism - computed[key] = function () { return fn(store); }; + // direct inline function use will lead to closure preserving oldVm. + // using partial to return function with only arguments preserved in closure enviroment. + computed[key] = partial(fn, store); Object.defineProperty(store.getters, key, { get: function () { return store._vm[key]; }, enumerable: true // for local getters @@ -989,7 +1000,7 @@ function getModuleByNamespace (store, helper, namespace) { var index = { Store: Store, install: install, - version: '3.1.0', + version: '3.1.1', mapState: mapState, mapMutations: mapMutations, mapGetters: mapGetters, diff --git a/dist/vuex.esm.browser.js b/dist/vuex.esm.browser.js new file mode 100644 index 000000000..679a5d842 --- /dev/null +++ b/dist/vuex.esm.browser.js @@ -0,0 +1,969 @@ +/** + * vuex v3.1.1 + * (c) 2019 Evan You + * @license MIT + */ +function applyMixin (Vue) { + const version = Number(Vue.version.split('.')[0]); + + if (version >= 2) { + Vue.mixin({ beforeCreate: vuexInit }); + } else { + // override init and inject vuex init procedure + // for 1.x backwards compatibility. + const _init = Vue.prototype._init; + Vue.prototype._init = function (options = {}) { + options.init = options.init + ? [vuexInit].concat(options.init) + : vuexInit; + _init.call(this, options); + }; + } + + /** + * Vuex init hook, injected into each instances init hooks list. + */ + + function vuexInit () { + const options = this.$options; + // store injection + if (options.store) { + this.$store = typeof options.store === 'function' + ? options.store() + : options.store; + } else if (options.parent && options.parent.$store) { + this.$store = options.parent.$store; + } + } +} + +const target = typeof window !== 'undefined' + ? window + : typeof global !== 'undefined' + ? global + : {}; +const devtoolHook = target.__VUE_DEVTOOLS_GLOBAL_HOOK__; + +function devtoolPlugin (store) { + if (!devtoolHook) return + + store._devtoolHook = devtoolHook; + + devtoolHook.emit('vuex:init', store); + + devtoolHook.on('vuex:travel-to-state', targetState => { + store.replaceState(targetState); + }); + + store.subscribe((mutation, state) => { + devtoolHook.emit('vuex:mutation', mutation, state); + }); +} + +/** + * Get the first item that pass the test + * by second argument function + * + * @param {Array} list + * @param {Function} f + * @return {*} + */ + +/** + * forEach for object + */ +function forEachValue (obj, fn) { + Object.keys(obj).forEach(key => fn(obj[key], key)); +} + +function isObject (obj) { + return obj !== null && typeof obj === 'object' +} + +function isPromise (val) { + return val && typeof val.then === 'function' +} + +function assert (condition, msg) { + if (!condition) throw new Error(`[vuex] ${msg}`) +} + +function partial (fn, arg) { + return function () { + return fn(arg) + } +} + +// Base data struct for store's module, package with some attribute and method +class Module { + constructor (rawModule, runtime) { + this.runtime = runtime; + // Store some children item + this._children = Object.create(null); + // Store the origin module object which passed by programmer + this._rawModule = rawModule; + const rawState = rawModule.state; + + // Store the origin module's state + this.state = (typeof rawState === 'function' ? rawState() : rawState) || {}; + } + + get namespaced () { + return !!this._rawModule.namespaced + } + + addChild (key, module) { + this._children[key] = module; + } + + removeChild (key) { + delete this._children[key]; + } + + getChild (key) { + return this._children[key] + } + + update (rawModule) { + this._rawModule.namespaced = rawModule.namespaced; + if (rawModule.actions) { + this._rawModule.actions = rawModule.actions; + } + if (rawModule.mutations) { + this._rawModule.mutations = rawModule.mutations; + } + if (rawModule.getters) { + this._rawModule.getters = rawModule.getters; + } + } + + forEachChild (fn) { + forEachValue(this._children, fn); + } + + forEachGetter (fn) { + if (this._rawModule.getters) { + forEachValue(this._rawModule.getters, fn); + } + } + + forEachAction (fn) { + if (this._rawModule.actions) { + forEachValue(this._rawModule.actions, fn); + } + } + + forEachMutation (fn) { + if (this._rawModule.mutations) { + forEachValue(this._rawModule.mutations, fn); + } + } +} + +class ModuleCollection { + constructor (rawRootModule) { + // register root module (Vuex.Store options) + this.register([], rawRootModule, false); + } + + get (path) { + return path.reduce((module, key) => { + return module.getChild(key) + }, this.root) + } + + getNamespace (path) { + let module = this.root; + return path.reduce((namespace, key) => { + module = module.getChild(key); + return namespace + (module.namespaced ? key + '/' : '') + }, '') + } + + update (rawRootModule) { + update([], this.root, rawRootModule); + } + + register (path, rawModule, runtime = true) { + { + assertRawModule(path, rawModule); + } + + const newModule = new Module(rawModule, runtime); + if (path.length === 0) { + this.root = newModule; + } else { + const parent = this.get(path.slice(0, -1)); + parent.addChild(path[path.length - 1], newModule); + } + + // register nested modules + if (rawModule.modules) { + forEachValue(rawModule.modules, (rawChildModule, key) => { + this.register(path.concat(key), rawChildModule, runtime); + }); + } + } + + unregister (path) { + const parent = this.get(path.slice(0, -1)); + const key = path[path.length - 1]; + if (!parent.getChild(key).runtime) return + + parent.removeChild(key); + } +} + +function update (path, targetModule, newModule) { + { + assertRawModule(path, newModule); + } + + // update target module + targetModule.update(newModule); + + // update nested modules + if (newModule.modules) { + for (const key in newModule.modules) { + if (!targetModule.getChild(key)) { + { + console.warn( + `[vuex] trying to add a new module '${key}' on hot reloading, ` + + 'manual reload is needed' + ); + } + return + } + update( + path.concat(key), + targetModule.getChild(key), + newModule.modules[key] + ); + } + } +} + +const functionAssert = { + assert: value => typeof value === 'function', + expected: 'function' +}; + +const objectAssert = { + assert: value => typeof value === 'function' || + (typeof value === 'object' && typeof value.handler === 'function'), + expected: 'function or object with "handler" function' +}; + +const assertTypes = { + getters: functionAssert, + mutations: functionAssert, + actions: objectAssert +}; + +function assertRawModule (path, rawModule) { + Object.keys(assertTypes).forEach(key => { + if (!rawModule[key]) return + + const assertOptions = assertTypes[key]; + + forEachValue(rawModule[key], (value, type) => { + assert( + assertOptions.assert(value), + makeAssertionMessage(path, key, type, value, assertOptions.expected) + ); + }); + }); +} + +function makeAssertionMessage (path, key, type, value, expected) { + let buf = `${key} should be ${expected} but "${key}.${type}"`; + if (path.length > 0) { + buf += ` in module "${path.join('.')}"`; + } + buf += ` is ${JSON.stringify(value)}.`; + return buf +} + +let Vue; // bind on install + +class Store { + constructor (options = {}) { + // Auto install if it is not done yet and `window` has `Vue`. + // To allow users to avoid auto-installation in some cases, + // this code should be placed here. See #731 + if (!Vue && typeof window !== 'undefined' && window.Vue) { + install(window.Vue); + } + + { + assert(Vue, `must call Vue.use(Vuex) before creating a store instance.`); + assert(typeof Promise !== 'undefined', `vuex requires a Promise polyfill in this browser.`); + assert(this instanceof Store, `store must be called with the new operator.`); + } + + const { + plugins = [], + strict = false + } = options; + + // store internal state + this._committing = false; + this._actions = Object.create(null); + this._actionSubscribers = []; + this._mutations = Object.create(null); + this._wrappedGetters = Object.create(null); + this._modules = new ModuleCollection(options); + this._modulesNamespaceMap = Object.create(null); + this._subscribers = []; + this._watcherVM = new Vue(); + + // bind commit and dispatch to self + const store = this; + const { dispatch, commit } = this; + this.dispatch = function boundDispatch (type, payload) { + return dispatch.call(store, type, payload) + }; + this.commit = function boundCommit (type, payload, options) { + return commit.call(store, type, payload, options) + }; + + // strict mode + this.strict = strict; + + const state = this._modules.root.state; + + // init root module. + // this also recursively registers all sub-modules + // and collects all module getters inside this._wrappedGetters + installModule(this, state, [], this._modules.root); + + // initialize the store vm, which is responsible for the reactivity + // (also registers _wrappedGetters as computed properties) + resetStoreVM(this, state); + + // apply plugins + plugins.forEach(plugin => plugin(this)); + + const useDevtools = options.devtools !== undefined ? options.devtools : Vue.config.devtools; + if (useDevtools) { + devtoolPlugin(this); + } + } + + get state () { + return this._vm._data.$$state + } + + set state (v) { + { + assert(false, `use store.replaceState() to explicit replace store state.`); + } + } + + commit (_type, _payload, _options) { + // check object-style commit + const { + type, + payload, + options + } = unifyObjectStyle(_type, _payload, _options); + + const mutation = { type, payload }; + const entry = this._mutations[type]; + if (!entry) { + { + console.error(`[vuex] unknown mutation type: ${type}`); + } + return + } + this._withCommit(() => { + entry.forEach(function commitIterator (handler) { + handler(payload); + }); + }); + this._subscribers.forEach(sub => sub(mutation, this.state)); + + if ( + options && options.silent + ) { + console.warn( + `[vuex] mutation type: ${type}. Silent option has been removed. ` + + 'Use the filter functionality in the vue-devtools' + ); + } + } + + dispatch (_type, _payload) { + // check object-style dispatch + const { + type, + payload + } = unifyObjectStyle(_type, _payload); + + const action = { type, payload }; + const entry = this._actions[type]; + if (!entry) { + { + console.error(`[vuex] unknown action type: ${type}`); + } + return + } + + try { + this._actionSubscribers + .filter(sub => sub.before) + .forEach(sub => sub.before(action, this.state)); + } catch (e) { + { + console.warn(`[vuex] error in before action subscribers: `); + console.error(e); + } + } + + const result = entry.length > 1 + ? Promise.all(entry.map(handler => handler(payload))) + : entry[0](payload); + + return result.then(res => { + try { + this._actionSubscribers + .filter(sub => sub.after) + .forEach(sub => sub.after(action, this.state)); + } catch (e) { + { + console.warn(`[vuex] error in after action subscribers: `); + console.error(e); + } + } + return res + }) + } + + subscribe (fn) { + return genericSubscribe(fn, this._subscribers) + } + + subscribeAction (fn) { + const subs = typeof fn === 'function' ? { before: fn } : fn; + return genericSubscribe(subs, this._actionSubscribers) + } + + watch (getter, cb, options) { + { + assert(typeof getter === 'function', `store.watch only accepts a function.`); + } + return this._watcherVM.$watch(() => getter(this.state, this.getters), cb, options) + } + + replaceState (state) { + this._withCommit(() => { + this._vm._data.$$state = state; + }); + } + + registerModule (path, rawModule, options = {}) { + if (typeof path === 'string') path = [path]; + + { + assert(Array.isArray(path), `module path must be a string or an Array.`); + assert(path.length > 0, 'cannot register the root module by using registerModule.'); + } + + this._modules.register(path, rawModule); + installModule(this, this.state, path, this._modules.get(path), options.preserveState); + // reset store to update getters... + resetStoreVM(this, this.state); + } + + unregisterModule (path) { + if (typeof path === 'string') path = [path]; + + { + assert(Array.isArray(path), `module path must be a string or an Array.`); + } + + this._modules.unregister(path); + this._withCommit(() => { + const parentState = getNestedState(this.state, path.slice(0, -1)); + Vue.delete(parentState, path[path.length - 1]); + }); + resetStore(this); + } + + hotUpdate (newOptions) { + this._modules.update(newOptions); + resetStore(this, true); + } + + _withCommit (fn) { + const committing = this._committing; + this._committing = true; + fn(); + this._committing = committing; + } +} + +function genericSubscribe (fn, subs) { + if (subs.indexOf(fn) < 0) { + subs.push(fn); + } + return () => { + const i = subs.indexOf(fn); + if (i > -1) { + subs.splice(i, 1); + } + } +} + +function resetStore (store, hot) { + store._actions = Object.create(null); + store._mutations = Object.create(null); + store._wrappedGetters = Object.create(null); + store._modulesNamespaceMap = Object.create(null); + const state = store.state; + // init all modules + installModule(store, state, [], store._modules.root, true); + // reset vm + resetStoreVM(store, state, hot); +} + +function resetStoreVM (store, state, hot) { + const oldVm = store._vm; + + // bind store public getters + store.getters = {}; + const wrappedGetters = store._wrappedGetters; + const computed = {}; + forEachValue(wrappedGetters, (fn, key) => { + // use computed to leverage its lazy-caching mechanism + // direct inline function use will lead to closure preserving oldVm. + // using partial to return function with only arguments preserved in closure enviroment. + computed[key] = partial(fn, store); + Object.defineProperty(store.getters, key, { + get: () => store._vm[key], + enumerable: true // for local getters + }); + }); + + // use a Vue instance to store the state tree + // suppress warnings just in case the user has added + // some funky global mixins + const silent = Vue.config.silent; + Vue.config.silent = true; + store._vm = new Vue({ + data: { + $$state: state + }, + computed + }); + Vue.config.silent = silent; + + // enable strict mode for new vm + if (store.strict) { + enableStrictMode(store); + } + + if (oldVm) { + if (hot) { + // dispatch changes in all subscribed watchers + // to force getter re-evaluation for hot reloading. + store._withCommit(() => { + oldVm._data.$$state = null; + }); + } + Vue.nextTick(() => oldVm.$destroy()); + } +} + +function installModule (store, rootState, path, module, hot) { + const isRoot = !path.length; + const namespace = store._modules.getNamespace(path); + + // register in namespace map + if (module.namespaced) { + store._modulesNamespaceMap[namespace] = module; + } + + // set state + if (!isRoot && !hot) { + const parentState = getNestedState(rootState, path.slice(0, -1)); + const moduleName = path[path.length - 1]; + store._withCommit(() => { + Vue.set(parentState, moduleName, module.state); + }); + } + + const local = module.context = makeLocalContext(store, namespace, path); + + module.forEachMutation((mutation, key) => { + const namespacedType = namespace + key; + registerMutation(store, namespacedType, mutation, local); + }); + + module.forEachAction((action, key) => { + const type = action.root ? key : namespace + key; + const handler = action.handler || action; + registerAction(store, type, handler, local); + }); + + module.forEachGetter((getter, key) => { + const namespacedType = namespace + key; + registerGetter(store, namespacedType, getter, local); + }); + + module.forEachChild((child, key) => { + installModule(store, rootState, path.concat(key), child, hot); + }); +} + +/** + * make localized dispatch, commit, getters and state + * if there is no namespace, just use root ones + */ +function makeLocalContext (store, namespace, path) { + const noNamespace = namespace === ''; + + const local = { + dispatch: noNamespace ? store.dispatch : (_type, _payload, _options) => { + const args = unifyObjectStyle(_type, _payload, _options); + const { payload, options } = args; + let { type } = args; + + if (!options || !options.root) { + type = namespace + type; + if (!store._actions[type]) { + console.error(`[vuex] unknown local action type: ${args.type}, global type: ${type}`); + return + } + } + + return store.dispatch(type, payload) + }, + + commit: noNamespace ? store.commit : (_type, _payload, _options) => { + const args = unifyObjectStyle(_type, _payload, _options); + const { payload, options } = args; + let { type } = args; + + if (!options || !options.root) { + type = namespace + type; + if (!store._mutations[type]) { + console.error(`[vuex] unknown local mutation type: ${args.type}, global type: ${type}`); + return + } + } + + store.commit(type, payload, options); + } + }; + + // getters and state object must be gotten lazily + // because they will be changed by vm update + Object.defineProperties(local, { + getters: { + get: noNamespace + ? () => store.getters + : () => makeLocalGetters(store, namespace) + }, + state: { + get: () => getNestedState(store.state, path) + } + }); + + return local +} + +function makeLocalGetters (store, namespace) { + const gettersProxy = {}; + + const splitPos = namespace.length; + Object.keys(store.getters).forEach(type => { + // skip if the target getter is not match this namespace + if (type.slice(0, splitPos) !== namespace) return + + // extract local getter type + const localType = type.slice(splitPos); + + // Add a port to the getters proxy. + // Define as getter property because + // we do not want to evaluate the getters in this time. + Object.defineProperty(gettersProxy, localType, { + get: () => store.getters[type], + enumerable: true + }); + }); + + return gettersProxy +} + +function registerMutation (store, type, handler, local) { + const entry = store._mutations[type] || (store._mutations[type] = []); + entry.push(function wrappedMutationHandler (payload) { + handler.call(store, local.state, payload); + }); +} + +function registerAction (store, type, handler, local) { + const entry = store._actions[type] || (store._actions[type] = []); + entry.push(function wrappedActionHandler (payload, cb) { + let res = handler.call(store, { + dispatch: local.dispatch, + commit: local.commit, + getters: local.getters, + state: local.state, + rootGetters: store.getters, + rootState: store.state + }, payload, cb); + if (!isPromise(res)) { + res = Promise.resolve(res); + } + if (store._devtoolHook) { + return res.catch(err => { + store._devtoolHook.emit('vuex:error', err); + throw err + }) + } else { + return res + } + }); +} + +function registerGetter (store, type, rawGetter, local) { + if (store._wrappedGetters[type]) { + { + console.error(`[vuex] duplicate getter key: ${type}`); + } + return + } + store._wrappedGetters[type] = function wrappedGetter (store) { + return rawGetter( + local.state, // local state + local.getters, // local getters + store.state, // root state + store.getters // root getters + ) + }; +} + +function enableStrictMode (store) { + store._vm.$watch(function () { return this._data.$$state }, () => { + { + assert(store._committing, `do not mutate vuex store state outside mutation handlers.`); + } + }, { deep: true, sync: true }); +} + +function getNestedState (state, path) { + return path.length + ? path.reduce((state, key) => state[key], state) + : state +} + +function unifyObjectStyle (type, payload, options) { + if (isObject(type) && type.type) { + options = payload; + payload = type; + type = type.type; + } + + { + assert(typeof type === 'string', `expects string as the type, but found ${typeof type}.`); + } + + return { type, payload, options } +} + +function install (_Vue) { + if (Vue && _Vue === Vue) { + { + console.error( + '[vuex] already installed. Vue.use(Vuex) should be called only once.' + ); + } + return + } + Vue = _Vue; + applyMixin(Vue); +} + +/** + * Reduce the code which written in Vue.js for getting the state. + * @param {String} [namespace] - Module's namespace + * @param {Object|Array} states # Object's item can be a function which accept state and getters for param, you can do something for state and getters in it. + * @param {Object} + */ +const mapState = normalizeNamespace((namespace, states) => { + const res = {}; + normalizeMap(states).forEach(({ key, val }) => { + res[key] = function mappedState () { + let state = this.$store.state; + let getters = this.$store.getters; + if (namespace) { + const module = getModuleByNamespace(this.$store, 'mapState', namespace); + if (!module) { + return + } + state = module.context.state; + getters = module.context.getters; + } + return typeof val === 'function' + ? val.call(this, state, getters) + : state[val] + }; + // mark vuex getter for devtools + res[key].vuex = true; + }); + return res +}); + +/** + * Reduce the code which written in Vue.js for committing the mutation + * @param {String} [namespace] - Module's namespace + * @param {Object|Array} mutations # Object's item can be a function which accept `commit` function as the first param, it can accept anthor params. You can commit mutation and do any other things in this function. specially, You need to pass anthor params from the mapped function. + * @return {Object} + */ +const mapMutations = normalizeNamespace((namespace, mutations) => { + const res = {}; + normalizeMap(mutations).forEach(({ key, val }) => { + res[key] = function mappedMutation (...args) { + // Get the commit method from store + let commit = this.$store.commit; + if (namespace) { + const module = getModuleByNamespace(this.$store, 'mapMutations', namespace); + if (!module) { + return + } + commit = module.context.commit; + } + return typeof val === 'function' + ? val.apply(this, [commit].concat(args)) + : commit.apply(this.$store, [val].concat(args)) + }; + }); + return res +}); + +/** + * Reduce the code which written in Vue.js for getting the getters + * @param {String} [namespace] - Module's namespace + * @param {Object|Array} getters + * @return {Object} + */ +const mapGetters = normalizeNamespace((namespace, getters) => { + const res = {}; + normalizeMap(getters).forEach(({ key, val }) => { + // The namespace has been mutated by normalizeNamespace + val = namespace + val; + res[key] = function mappedGetter () { + if (namespace && !getModuleByNamespace(this.$store, 'mapGetters', namespace)) { + return + } + if (!(val in this.$store.getters)) { + console.error(`[vuex] unknown getter: ${val}`); + return + } + return this.$store.getters[val] + }; + // mark vuex getter for devtools + res[key].vuex = true; + }); + return res +}); + +/** + * Reduce the code which written in Vue.js for dispatch the action + * @param {String} [namespace] - Module's namespace + * @param {Object|Array} actions # Object's item can be a function which accept `dispatch` function as the first param, it can accept anthor params. You can dispatch action and do any other things in this function. specially, You need to pass anthor params from the mapped function. + * @return {Object} + */ +const mapActions = normalizeNamespace((namespace, actions) => { + const res = {}; + normalizeMap(actions).forEach(({ key, val }) => { + res[key] = function mappedAction (...args) { + // get dispatch function from store + let dispatch = this.$store.dispatch; + if (namespace) { + const module = getModuleByNamespace(this.$store, 'mapActions', namespace); + if (!module) { + return + } + dispatch = module.context.dispatch; + } + return typeof val === 'function' + ? val.apply(this, [dispatch].concat(args)) + : dispatch.apply(this.$store, [val].concat(args)) + }; + }); + return res +}); + +/** + * Rebinding namespace param for mapXXX function in special scoped, and return them by simple object + * @param {String} namespace + * @return {Object} + */ +const createNamespacedHelpers = (namespace) => ({ + mapState: mapState.bind(null, namespace), + mapGetters: mapGetters.bind(null, namespace), + mapMutations: mapMutations.bind(null, namespace), + mapActions: mapActions.bind(null, namespace) +}); + +/** + * Normalize the map + * normalizeMap([1, 2, 3]) => [ { key: 1, val: 1 }, { key: 2, val: 2 }, { key: 3, val: 3 } ] + * normalizeMap({a: 1, b: 2, c: 3}) => [ { key: 'a', val: 1 }, { key: 'b', val: 2 }, { key: 'c', val: 3 } ] + * @param {Array|Object} map + * @return {Object} + */ +function normalizeMap (map) { + return Array.isArray(map) + ? map.map(key => ({ key, val: key })) + : Object.keys(map).map(key => ({ key, val: map[key] })) +} + +/** + * Return a function expect two param contains namespace and map. it will normalize the namespace and then the param's function will handle the new namespace and the map. + * @param {Function} fn + * @return {Function} + */ +function normalizeNamespace (fn) { + return (namespace, map) => { + if (typeof namespace !== 'string') { + map = namespace; + namespace = ''; + } else if (namespace.charAt(namespace.length - 1) !== '/') { + namespace += '/'; + } + return fn(namespace, map) + } +} + +/** + * Search a special module from store by namespace. if module not exist, print error message. + * @param {Object} store + * @param {String} helper + * @param {String} namespace + * @return {Object} + */ +function getModuleByNamespace (store, helper, namespace) { + const module = store._modulesNamespaceMap[namespace]; + if (!module) { + console.error(`[vuex] module namespace not found in ${helper}(): ${namespace}`); + } + return module +} + +var index_esm = { + Store, + install, + version: '3.1.1', + mapState, + mapMutations, + mapGetters, + mapActions, + createNamespacedHelpers +}; + +export default index_esm; +export { Store, install, mapState, mapMutations, mapGetters, mapActions, createNamespacedHelpers }; diff --git a/dist/vuex.esm.browser.min.js b/dist/vuex.esm.browser.min.js new file mode 100644 index 000000000..1261afbd1 --- /dev/null +++ b/dist/vuex.esm.browser.min.js @@ -0,0 +1,6 @@ +/** + * vuex v3.1.1 + * (c) 2019 Evan You + * @license MIT + */ +const t=("undefined"!=typeof window?window:"undefined"!=typeof global?global:{}).__VUE_DEVTOOLS_GLOBAL_HOOK__;function e(t,e){Object.keys(t).forEach(s=>e(t[s],s))}class s{constructor(t,e){this.runtime=e,this._children=Object.create(null),this._rawModule=t;const s=t.state;this.state=("function"==typeof s?s():s)||{}}get namespaced(){return!!this._rawModule.namespaced}addChild(t,e){this._children[t]=e}removeChild(t){delete this._children[t]}getChild(t){return this._children[t]}update(t){this._rawModule.namespaced=t.namespaced,t.actions&&(this._rawModule.actions=t.actions),t.mutations&&(this._rawModule.mutations=t.mutations),t.getters&&(this._rawModule.getters=t.getters)}forEachChild(t){e(this._children,t)}forEachGetter(t){this._rawModule.getters&&e(this._rawModule.getters,t)}forEachAction(t){this._rawModule.actions&&e(this._rawModule.actions,t)}forEachMutation(t){this._rawModule.mutations&&e(this._rawModule.mutations,t)}}class i{constructor(t){this.register([],t,!1)}get(t){return t.reduce((t,e)=>t.getChild(e),this.root)}getNamespace(t){let e=this.root;return t.reduce((t,s)=>t+((e=e.getChild(s)).namespaced?s+"/":""),"")}update(t){!function t(e,s,i){s.update(i);if(i.modules)for(const o in i.modules){if(!s.getChild(o))return;t(e.concat(o),s.getChild(o),i.modules[o])}}([],this.root,t)}register(t,i,o=!0){const n=new s(i,o);if(0===t.length)this.root=n;else{this.get(t.slice(0,-1)).addChild(t[t.length-1],n)}i.modules&&e(i.modules,(e,s)=>{this.register(t.concat(s),e,o)})}unregister(t){const e=this.get(t.slice(0,-1)),s=t[t.length-1];e.getChild(s).runtime&&e.removeChild(s)}}let o;class n{constructor(e={}){!o&&"undefined"!=typeof window&&window.Vue&&d(window.Vue);const{plugins:s=[],strict:n=!1}=e;this._committing=!1,this._actions=Object.create(null),this._actionSubscribers=[],this._mutations=Object.create(null),this._wrappedGetters=Object.create(null),this._modules=new i(e),this._modulesNamespaceMap=Object.create(null),this._subscribers=[],this._watcherVM=new o;const r=this,{dispatch:c,commit:h}=this;this.dispatch=function(t,e){return c.call(r,t,e)},this.commit=function(t,e,s){return h.call(r,t,e,s)},this.strict=n;const l=this._modules.root.state;u(this,l,[],this._modules.root),a(this,l),s.forEach(t=>t(this)),(void 0!==e.devtools?e.devtools:o.config.devtools)&&function(e){t&&(e._devtoolHook=t,t.emit("vuex:init",e),t.on("vuex:travel-to-state",t=>{e.replaceState(t)}),e.subscribe((e,s)=>{t.emit("vuex:mutation",e,s)}))}(this)}get state(){return this._vm._data.$$state}set state(t){}commit(t,e,s){const{type:i,payload:o,options:n}=l(t,e,s),r={type:i,payload:o},c=this._mutations[i];c&&(this._withCommit(()=>{c.forEach(function(t){t(o)})}),this._subscribers.forEach(t=>t(r,this.state)))}dispatch(t,e){const{type:s,payload:i}=l(t,e),o={type:s,payload:i},n=this._actions[s];if(n){try{this._actionSubscribers.filter(t=>t.before).forEach(t=>t.before(o,this.state))}catch(t){}return(n.length>1?Promise.all(n.map(t=>t(i))):n[0](i)).then(t=>{try{this._actionSubscribers.filter(t=>t.after).forEach(t=>t.after(o,this.state))}catch(t){}return t})}}subscribe(t){return r(t,this._subscribers)}subscribeAction(t){return r("function"==typeof t?{before:t}:t,this._actionSubscribers)}watch(t,e,s){return this._watcherVM.$watch(()=>t(this.state,this.getters),e,s)}replaceState(t){this._withCommit(()=>{this._vm._data.$$state=t})}registerModule(t,e,s={}){"string"==typeof t&&(t=[t]),this._modules.register(t,e),u(this,this.state,t,this._modules.get(t),s.preserveState),a(this,this.state)}unregisterModule(t){"string"==typeof t&&(t=[t]),this._modules.unregister(t),this._withCommit(()=>{const e=h(this.state,t.slice(0,-1));o.delete(e,t[t.length-1])}),c(this)}hotUpdate(t){this._modules.update(t),c(this,!0)}_withCommit(t){const e=this._committing;this._committing=!0,t(),this._committing=e}}function r(t,e){return e.indexOf(t)<0&&e.push(t),()=>{const s=e.indexOf(t);s>-1&&e.splice(s,1)}}function c(t,e){t._actions=Object.create(null),t._mutations=Object.create(null),t._wrappedGetters=Object.create(null),t._modulesNamespaceMap=Object.create(null);const s=t.state;u(t,s,[],t._modules.root,!0),a(t,s,e)}function a(t,s,i){const n=t._vm;t.getters={};const r=t._wrappedGetters,c={};e(r,(e,s)=>{c[s]=function(t,e){return function(){return t(e)}}(e,t),Object.defineProperty(t.getters,s,{get:()=>t._vm[s],enumerable:!0})});const a=o.config.silent;o.config.silent=!0,t._vm=new o({data:{$$state:s},computed:c}),o.config.silent=a,t.strict&&function(t){t._vm.$watch(function(){return this._data.$$state},()=>{},{deep:!0,sync:!0})}(t),n&&(i&&t._withCommit(()=>{n._data.$$state=null}),o.nextTick(()=>n.$destroy()))}function u(t,e,s,i,n){const r=!s.length,c=t._modules.getNamespace(s);if(i.namespaced&&(t._modulesNamespaceMap[c]=i),!r&&!n){const n=h(e,s.slice(0,-1)),r=s[s.length-1];t._withCommit(()=>{o.set(n,r,i.state)})}const a=i.context=function(t,e,s){const i=""===e,o={dispatch:i?t.dispatch:(s,i,o)=>{const n=l(s,i,o),{payload:r,options:c}=n;let{type:a}=n;return c&&c.root||(a=e+a),t.dispatch(a,r)},commit:i?t.commit:(s,i,o)=>{const n=l(s,i,o),{payload:r,options:c}=n;let{type:a}=n;c&&c.root||(a=e+a),t.commit(a,r,c)}};return Object.defineProperties(o,{getters:{get:i?()=>t.getters:()=>(function(t,e){const s={},i=e.length;return Object.keys(t.getters).forEach(o=>{if(o.slice(0,i)!==e)return;const n=o.slice(i);Object.defineProperty(s,n,{get:()=>t.getters[o],enumerable:!0})}),s})(t,e)},state:{get:()=>h(t.state,s)}}),o}(t,c,s);i.forEachMutation((e,s)=>{!function(t,e,s,i){(t._mutations[e]||(t._mutations[e]=[])).push(function(e){s.call(t,i.state,e)})}(t,c+s,e,a)}),i.forEachAction((e,s)=>{const i=e.root?s:c+s,o=e.handler||e;!function(t,e,s,i){(t._actions[e]||(t._actions[e]=[])).push(function(e,o){let n=s.call(t,{dispatch:i.dispatch,commit:i.commit,getters:i.getters,state:i.state,rootGetters:t.getters,rootState:t.state},e,o);var r;return(r=n)&&"function"==typeof r.then||(n=Promise.resolve(n)),t._devtoolHook?n.catch(e=>{throw t._devtoolHook.emit("vuex:error",e),e}):n})}(t,i,o,a)}),i.forEachGetter((e,s)=>{!function(t,e,s,i){if(t._wrappedGetters[e])return;t._wrappedGetters[e]=function(t){return s(i.state,i.getters,t.state,t.getters)}}(t,c+s,e,a)}),i.forEachChild((i,o)=>{u(t,e,s.concat(o),i,n)})}function h(t,e){return e.length?e.reduce((t,e)=>t[e],t):t}function l(t,e,s){var i;return null!==(i=t)&&"object"==typeof i&&t.type&&(s=e,e=t,t=t.type),{type:t,payload:e,options:s}}function d(t){o&&t===o||function(t){if(Number(t.version.split(".")[0])>=2)t.mixin({beforeCreate:e});else{const s=t.prototype._init;t.prototype._init=function(t={}){t.init=t.init?[e].concat(t.init):e,s.call(this,t)}}function e(){const t=this.$options;t.store?this.$store="function"==typeof t.store?t.store():t.store:t.parent&&t.parent.$store&&(this.$store=t.parent.$store)}}(o=t)}const p=b((t,e)=>{const s={};return y(e).forEach(({key:e,val:i})=>{s[e]=function(){let e=this.$store.state,s=this.$store.getters;if(t){const i=w(this.$store,"mapState",t);if(!i)return;e=i.context.state,s=i.context.getters}return"function"==typeof i?i.call(this,e,s):e[i]},s[e].vuex=!0}),s}),m=b((t,e)=>{const s={};return y(e).forEach(({key:e,val:i})=>{s[e]=function(...e){let s=this.$store.commit;if(t){const e=w(this.$store,"mapMutations",t);if(!e)return;s=e.context.commit}return"function"==typeof i?i.apply(this,[s].concat(e)):s.apply(this.$store,[i].concat(e))}}),s}),f=b((t,e)=>{const s={};return y(e).forEach(({key:e,val:i})=>{i=t+i,s[e]=function(){if(!t||w(this.$store,"mapGetters",t))return this.$store.getters[i]},s[e].vuex=!0}),s}),_=b((t,e)=>{const s={};return y(e).forEach(({key:e,val:i})=>{s[e]=function(...e){let s=this.$store.dispatch;if(t){const e=w(this.$store,"mapActions",t);if(!e)return;s=e.context.dispatch}return"function"==typeof i?i.apply(this,[s].concat(e)):s.apply(this.$store,[i].concat(e))}}),s}),g=t=>({mapState:p.bind(null,t),mapGetters:f.bind(null,t),mapMutations:m.bind(null,t),mapActions:_.bind(null,t)});function y(t){return Array.isArray(t)?t.map(t=>({key:t,val:t})):Object.keys(t).map(e=>({key:e,val:t[e]}))}function b(t){return(e,s)=>("string"!=typeof e?(s=e,e=""):"/"!==e.charAt(e.length-1)&&(e+="/"),t(e,s))}function w(t,e,s){return t._modulesNamespaceMap[s]}export default{Store:n,install:d,version:"3.1.1",mapState:p,mapMutations:m,mapGetters:f,mapActions:_,createNamespacedHelpers:g};export{n as Store,d as install,p as mapState,m as mapMutations,f as mapGetters,_ as mapActions,g as createNamespacedHelpers}; \ No newline at end of file diff --git a/dist/vuex.esm.js b/dist/vuex.esm.js index da94e9b59..982977b7a 100644 --- a/dist/vuex.esm.js +++ b/dist/vuex.esm.js @@ -1,5 +1,5 @@ /** - * vuex v3.1.0 + * vuex v3.1.1 * (c) 2019 Evan You * @license MIT */ @@ -39,9 +39,12 @@ function applyMixin (Vue) { } } -var devtoolHook = - typeof window !== 'undefined' && - window.__VUE_DEVTOOLS_GLOBAL_HOOK__; +var target = typeof window !== 'undefined' + ? window + : typeof global !== 'undefined' + ? global + : {}; +var devtoolHook = target.__VUE_DEVTOOLS_GLOBAL_HOOK__; function devtoolPlugin (store) { if (!devtoolHook) { return } @@ -87,6 +90,12 @@ function assert (condition, msg) { if (!condition) { throw new Error(("[vuex] " + msg)) } } +function partial (fn, arg) { + return function () { + return fn(arg) + } +} + // Base data struct for store's module, package with some attribute and method var Module = function Module (rawModule, runtime) { this.runtime = runtime; @@ -548,7 +557,9 @@ function resetStoreVM (store, state, hot) { var computed = {}; forEachValue(wrappedGetters, function (fn, key) { // use computed to leverage its lazy-caching mechanism - computed[key] = function () { return fn(store); }; + // direct inline function use will lead to closure preserving oldVm. + // using partial to return function with only arguments preserved in closure enviroment. + computed[key] = partial(fn, store); Object.defineProperty(store.getters, key, { get: function () { return store._vm[key]; }, enumerable: true // for local getters @@ -987,7 +998,7 @@ function getModuleByNamespace (store, helper, namespace) { var index_esm = { Store: Store, install: install, - version: '3.1.0', + version: '3.1.1', mapState: mapState, mapMutations: mapMutations, mapGetters: mapGetters, diff --git a/dist/vuex.js b/dist/vuex.js index bae565303..8ac0fe0dc 100644 --- a/dist/vuex.js +++ b/dist/vuex.js @@ -1,5 +1,5 @@ /** - * vuex v3.1.0 + * vuex v3.1.1 * (c) 2019 Evan You * @license MIT */ @@ -45,9 +45,12 @@ } } - var devtoolHook = - typeof window !== 'undefined' && - window.__VUE_DEVTOOLS_GLOBAL_HOOK__; + var target = typeof window !== 'undefined' + ? window + : typeof global !== 'undefined' + ? global + : {}; + var devtoolHook = target.__VUE_DEVTOOLS_GLOBAL_HOOK__; function devtoolPlugin (store) { if (!devtoolHook) { return } @@ -93,6 +96,12 @@ if (!condition) { throw new Error(("[vuex] " + msg)) } } + function partial (fn, arg) { + return function () { + return fn(arg) + } + } + // Base data struct for store's module, package with some attribute and method var Module = function Module (rawModule, runtime) { this.runtime = runtime; @@ -553,7 +562,9 @@ var computed = {}; forEachValue(wrappedGetters, function (fn, key) { // use computed to leverage its lazy-caching mechanism - computed[key] = function () { return fn(store); }; + // direct inline function use will lead to closure preserving oldVm. + // using partial to return function with only arguments preserved in closure enviroment. + computed[key] = partial(fn, store); Object.defineProperty(store.getters, key, { get: function () { return store._vm[key]; }, enumerable: true // for local getters @@ -992,7 +1003,7 @@ var index = { Store: Store, install: install, - version: '3.1.0', + version: '3.1.1', mapState: mapState, mapMutations: mapMutations, mapGetters: mapGetters, diff --git a/dist/vuex.min.js b/dist/vuex.min.js index 15b9039cc..787aee830 100644 --- a/dist/vuex.min.js +++ b/dist/vuex.min.js @@ -1,6 +1,6 @@ /** - * vuex v3.1.0 + * vuex v3.1.1 * (c) 2019 Evan You * @license MIT */ -!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(t=t||self).Vuex=e()}(this,function(){"use strict";var u="undefined"!=typeof window&&window.__VUE_DEVTOOLS_GLOBAL_HOOK__;function a(e,n){Object.keys(e).forEach(function(t){return n(e[t],t)})}var r=function(t,e){this.runtime=e,this._children=Object.create(null);var n=(this._rawModule=t).state;this.state=("function"==typeof n?n():n)||{}},t={namespaced:{configurable:!0}};t.namespaced.get=function(){return!!this._rawModule.namespaced},r.prototype.addChild=function(t,e){this._children[t]=e},r.prototype.removeChild=function(t){delete this._children[t]},r.prototype.getChild=function(t){return this._children[t]},r.prototype.update=function(t){this._rawModule.namespaced=t.namespaced,t.actions&&(this._rawModule.actions=t.actions),t.mutations&&(this._rawModule.mutations=t.mutations),t.getters&&(this._rawModule.getters=t.getters)},r.prototype.forEachChild=function(t){a(this._children,t)},r.prototype.forEachGetter=function(t){this._rawModule.getters&&a(this._rawModule.getters,t)},r.prototype.forEachAction=function(t){this._rawModule.actions&&a(this._rawModule.actions,t)},r.prototype.forEachMutation=function(t){this._rawModule.mutations&&a(this._rawModule.mutations,t)},Object.defineProperties(r.prototype,t);var m,f=function(t){this.register([],t,!1)};f.prototype.get=function(t){return t.reduce(function(t,e){return t.getChild(e)},this.root)},f.prototype.getNamespace=function(t){var n=this.root;return t.reduce(function(t,e){return t+((n=n.getChild(e)).namespaced?e+"/":"")},"")},f.prototype.update=function(t){!function t(e,n,o){n.update(o);if(o.modules)for(var i in o.modules){if(!n.getChild(i))return;t(e.concat(i),n.getChild(i),o.modules[i])}}([],this.root,t)},f.prototype.register=function(n,t,o){var i=this;void 0===o&&(o=!0);var e=new r(t,o);0===n.length?this.root=e:this.get(n.slice(0,-1)).addChild(n[n.length-1],e);t.modules&&a(t.modules,function(t,e){i.register(n.concat(e),t,o)})},f.prototype.unregister=function(t){var e=this.get(t.slice(0,-1)),n=t[t.length-1];e.getChild(n).runtime&&e.removeChild(n)};var e=function(t){var e=this;void 0===t&&(t={}),!m&&"undefined"!=typeof window&&window.Vue&&p(window.Vue);var n=t.plugins;void 0===n&&(n=[]);var o=t.strict;void 0===o&&(o=!1),this._committing=!1,this._actions=Object.create(null),this._actionSubscribers=[],this._mutations=Object.create(null),this._wrappedGetters=Object.create(null),this._modules=new f(t),this._modulesNamespaceMap=Object.create(null),this._subscribers=[],this._watcherVM=new m;var i=this,r=this.dispatch,s=this.commit;this.dispatch=function(t,e){return r.call(i,t,e)},this.commit=function(t,e,n){return s.call(i,t,e,n)},this.strict=o;var a,c=this._modules.root.state;v(this,c,[],this._modules.root),h(this,c),n.forEach(function(t){return t(e)}),(void 0!==t.devtools?t.devtools:m.config.devtools)&&(a=this,u&&((a._devtoolHook=u).emit("vuex:init",a),u.on("vuex:travel-to-state",function(t){a.replaceState(t)}),a.subscribe(function(t,e){u.emit("vuex:mutation",t,e)})))},n={state:{configurable:!0}};function o(e,n){return n.indexOf(e)<0&&n.push(e),function(){var t=n.indexOf(e);-1-1&&e.splice(n,1)}}function u(t,e){t._actions=Object.create(null),t._mutations=Object.create(null),t._wrappedGetters=Object.create(null),t._modulesNamespaceMap=Object.create(null);var n=t.state;p(t,n,[],t._modules.root,!0),f(t,n,e)}function f(t,n,o){var r=t._vm;t.getters={};var s=t._wrappedGetters,a={};e(s,function(e,n){a[n]=function(t,e){return function(){return t(e)}}(e,t),Object.defineProperty(t.getters,n,{get:function(){return t._vm[n]},enumerable:!0})});var c=i.config.silent;i.config.silent=!0,t._vm=new i({data:{$$state:n},computed:a}),i.config.silent=c,t.strict&&function(t){t._vm.$watch(function(){return this._data.$$state},function(){},{deep:!0,sync:!0})}(t),r&&(o&&t._withCommit(function(){r._data.$$state=null}),i.nextTick(function(){return r.$destroy()}))}function p(t,e,n,o,r){var s=!n.length,a=t._modules.getNamespace(n);if(o.namespaced&&(t._modulesNamespaceMap[a]=o),!s&&!r){var c=h(e,n.slice(0,-1)),u=n[n.length-1];t._withCommit(function(){i.set(c,u,o.state)})}var f=o.context=function(t,e,n){var o=""===e,i={dispatch:o?t.dispatch:function(n,o,i){var r=l(n,o,i),s=r.payload,a=r.options,c=r.type;return a&&a.root||(c=e+c),t.dispatch(c,s)},commit:o?t.commit:function(n,o,i){var r=l(n,o,i),s=r.payload,a=r.options,c=r.type;a&&a.root||(c=e+c),t.commit(c,s,a)}};return Object.defineProperties(i,{getters:{get:o?function(){return t.getters}:function(){return function(t,e){var n={},o=e.length;return Object.keys(t.getters).forEach(function(i){if(i.slice(0,o)===e){var r=i.slice(o);Object.defineProperty(n,r,{get:function(){return t.getters[i]},enumerable:!0})}}),n}(t,e)}},state:{get:function(){return h(t.state,n)}}}),i}(t,a,n);o.forEachMutation(function(e,n){!function(t,e,n,o){(t._mutations[e]||(t._mutations[e]=[])).push(function(e){n.call(t,o.state,e)})}(t,a+n,e,f)}),o.forEachAction(function(e,n){var o=e.root?n:a+n,i=e.handler||e;!function(t,e,n,o){(t._actions[e]||(t._actions[e]=[])).push(function(e,i){var r,s=n.call(t,{dispatch:o.dispatch,commit:o.commit,getters:o.getters,state:o.state,rootGetters:t.getters,rootState:t.state},e,i);return(r=s)&&"function"==typeof r.then||(s=Promise.resolve(s)),t._devtoolHook?s.catch(function(e){throw t._devtoolHook.emit("vuex:error",e),e}):s})}(t,o,i,f)}),o.forEachGetter(function(e,n){!function(t,e,n,o){if(t._wrappedGetters[e])return;t._wrappedGetters[e]=function(t){return n(o.state,o.getters,t.state,t.getters)}}(t,a+n,e,f)}),o.forEachChild(function(o,i){p(t,e,n.concat(i),o,r)})}function h(t,e){return e.length?e.reduce(function(t,e){return t[e]},t):t}function l(t,e,n){var o;return null!==(o=t)&&"object"==typeof o&&t.type&&(n=e,e=t,t=t.type),{type:t,payload:e,options:n}}function d(t){i&&t===i||function(t){if(Number(t.version.split(".")[0])>=2)t.mixin({beforeCreate:n});else{var e=t.prototype._init;t.prototype._init=function(t){void 0===t&&(t={}),t.init=t.init?[n].concat(t.init):n,e.call(this,t)}}function n(){var t=this.$options;t.store?this.$store="function"==typeof t.store?t.store():t.store:t.parent&&t.parent.$store&&(this.$store=t.parent.$store)}}(i=t)}a.state.get=function(){return this._vm._data.$$state},a.state.set=function(t){},s.prototype.commit=function(t,e,n){var o=this,i=l(t,e,n),r=i.type,s=i.payload,a={type:r,payload:s},c=this._mutations[r];c&&(this._withCommit(function(){c.forEach(function(t){t(s)})}),this._subscribers.forEach(function(t){return t(a,o.state)}))},s.prototype.dispatch=function(t,e){var n=this,o=l(t,e),i=o.type,r=o.payload,s={type:i,payload:r},a=this._actions[i];if(a){try{this._actionSubscribers.filter(function(t){return t.before}).forEach(function(t){return t.before(s,n.state)})}catch(t){}return(a.length>1?Promise.all(a.map(function(t){return t(r)})):a[0](r)).then(function(t){try{n._actionSubscribers.filter(function(t){return t.after}).forEach(function(t){return t.after(s,n.state)})}catch(t){}return t})}},s.prototype.subscribe=function(t){return c(t,this._subscribers)},s.prototype.subscribeAction=function(t){return c("function"==typeof t?{before:t}:t,this._actionSubscribers)},s.prototype.watch=function(t,e,n){var o=this;return this._watcherVM.$watch(function(){return t(o.state,o.getters)},e,n)},s.prototype.replaceState=function(t){var e=this;this._withCommit(function(){e._vm._data.$$state=t})},s.prototype.registerModule=function(t,e,n){void 0===n&&(n={}),"string"==typeof t&&(t=[t]),this._modules.register(t,e),p(this,this.state,t,this._modules.get(t),n.preserveState),f(this,this.state)},s.prototype.unregisterModule=function(t){var e=this;"string"==typeof t&&(t=[t]),this._modules.unregister(t),this._withCommit(function(){var n=h(e.state,t.slice(0,-1));i.delete(n,t[t.length-1])}),u(this)},s.prototype.hotUpdate=function(t){this._modules.update(t),u(this,!0)},s.prototype._withCommit=function(t){var e=this._committing;this._committing=!0,t(),this._committing=e},Object.defineProperties(s.prototype,a);var m=b(function(t,e){var n={};return g(e).forEach(function(e){var o=e.key,i=e.val;n[o]=function(){var e=this.$store.state,n=this.$store.getters;if(t){var o=w(this.$store,"mapState",t);if(!o)return;e=o.context.state,n=o.context.getters}return"function"==typeof i?i.call(this,e,n):e[i]},n[o].vuex=!0}),n}),v=b(function(t,e){var n={};return g(e).forEach(function(e){var o=e.key,i=e.val;n[o]=function(){for(var e=[],n=arguments.length;n--;)e[n]=arguments[n];var o=this.$store.commit;if(t){var r=w(this.$store,"mapMutations",t);if(!r)return;o=r.context.commit}return"function"==typeof i?i.apply(this,[o].concat(e)):o.apply(this.$store,[i].concat(e))}}),n}),_=b(function(t,e){var n={};return g(e).forEach(function(e){var o=e.key,i=e.val;i=t+i,n[o]=function(){if(!t||w(this.$store,"mapGetters",t))return this.$store.getters[i]},n[o].vuex=!0}),n}),y=b(function(t,e){var n={};return g(e).forEach(function(e){var o=e.key,i=e.val;n[o]=function(){for(var e=[],n=arguments.length;n--;)e[n]=arguments[n];var o=this.$store.dispatch;if(t){var r=w(this.$store,"mapActions",t);if(!r)return;o=r.context.dispatch}return"function"==typeof i?i.apply(this,[o].concat(e)):o.apply(this.$store,[i].concat(e))}}),n});function g(t){return Array.isArray(t)?t.map(function(t){return{key:t,val:t}}):Object.keys(t).map(function(e){return{key:e,val:t[e]}})}function b(t){return function(e,n){return"string"!=typeof e?(n=e,e=""):"/"!==e.charAt(e.length-1)&&(e+="/"),t(e,n)}}function w(t,e,n){return t._modulesNamespaceMap[n]}return{Store:s,install:d,version:"3.1.1",mapState:m,mapMutations:v,mapGetters:_,mapActions:y,createNamespacedHelpers:function(t){return{mapState:m.bind(null,t),mapGetters:_.bind(null,t),mapMutations:v.bind(null,t),mapActions:y.bind(null,t)}}}}); \ No newline at end of file From ffc7d00314a371c09d288bc5123793031d182cd2 Mon Sep 17 00:00:00 2001 From: Guillaume Chau Date: Wed, 8 May 2019 23:24:12 +0200 Subject: [PATCH 29/29] [release] 3.1.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 675e1ee36..23f421901 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "vuex", - "version": "3.1.0", + "version": "3.1.1", "description": "state management for Vue.js", "main": "dist/vuex.common.js", "module": "dist/vuex.esm.js", pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy