14 |
15 |
16 |
38 |
--------------------------------------------------------------------------------
/docs/ja/installation.md:
--------------------------------------------------------------------------------
1 | # インストール
2 |
3 | ### 直接ダウンロードする / CDN
4 |
5 | [https://unpkg.com/vuex](https://unpkg.com/vuex)
6 |
7 |
8 | [Unpkg.com](https://unpkg.com) で NPM ベースの CDN リンクが提供されています。上記リンクは常に NPM の最新のリリースを指します。`https://unpkg.com/vuex@2.0.0` のような URL によって特定のバージョン/タグを利用することもできます。
9 |
10 |
11 | Vue のあとで `vuex` を取り込むと自動的に Vuex が導入されます:
12 |
13 | ``` html
14 |
15 |
16 | ```
17 |
18 | ### NPM
19 |
20 | ``` bash
21 | npm install vuex --save
22 | ```
23 |
24 | ### Yarn
25 |
26 | ``` bash
27 | yarn add vuex
28 | ```
29 |
30 | モジュールシステムで利用される場合、 `Vue.use()` によって Vuex を明示的に導入する必要があります:
31 |
32 | ``` js
33 | import Vue from 'vue'
34 | import Vuex from 'vuex'
35 |
36 | Vue.use(Vuex)
37 | ```
38 |
39 | グローバルなスクリプトタグを利用する場合にはこのようにする必要はありません。
40 |
41 | ### 開発版ビルド
42 |
43 | 最新の開発版ビルドを利用したい場合には、 Github から直接クローンし `vuex` を自身でビルドする必要があります。
44 |
45 | ``` bash
46 | git clone https://github.com/vuejs/vuex.git node_modules/vuex
47 | cd node_modules/vuex
48 | npm install
49 | npm run build
50 | ```
51 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015-2016 Evan You
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in
13 | all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | THE SOFTWARE.
22 |
--------------------------------------------------------------------------------
/examples/chat/components/ThreadSection.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Unread threads: {{ unreadCount }}
6 |
7 |
8 |
9 |
15 |
16 |
17 |
18 |
19 |
20 |
48 |
--------------------------------------------------------------------------------
/docs/zh-cn/hot-reload.md:
--------------------------------------------------------------------------------
1 | # 热重载
2 |
3 | 使用 webpack 的 [Hot Module Replacement API](https://webpack.github.io/docs/hot-module-replacement.html),Vuex 支持在开发过程中热重载 mutation、modules、actions、和getters。你也可以在 Browserify 中使用 [browserify-hmr](https://github.com/AgentME/browserify-hmr/) 插件。
4 |
5 | 对于 mutation 和模块,你需要使用 `store.hotUpdate()` 方法:
6 |
7 | ``` js
8 | // store.js
9 | import Vue from 'vue'
10 | import Vuex from 'vuex'
11 | import mutations from './mutations'
12 | import moduleA from './modules/a'
13 |
14 | Vue.use(Vuex)
15 |
16 | const state = { ... }
17 |
18 | const store = new Vuex.Store({
19 | state,
20 | mutations,
21 | modules: {
22 | a: moduleA
23 | }
24 | })
25 |
26 | if (module.hot) {
27 | // 使 actions 和 mutations 成为可热重载模块
28 | module.hot.accept(['./mutations', './modules/a'], () => {
29 | // 获取更新后的模块
30 | // 因为 babel 6 的模块编译格式问题,这里需要加上 .default
31 | const newMutations = require('./mutations').default
32 | const newModuleA = require('./modules/a').default
33 | // 加载新模块
34 | store.hotUpdate({
35 | mutations: newMutations,
36 | modules: {
37 | a: newModuleA
38 | }
39 | })
40 | })
41 | }
42 | ```
43 |
44 | 参考热重载示例 [counter-hot](https://github.com/vuejs/vuex/tree/dev/examples/counter-hot)。
45 |
--------------------------------------------------------------------------------
/docs/kr/hot-reload.md:
--------------------------------------------------------------------------------
1 | # 핫 리로딩
2 |
3 | Vuex는 Webpack의 [핫 모듈 변경 API](https://webpack.github.io/docs/hot-module-replacement.html)를 사용하여 개발 중에 핫 리로드 변이, 모듈, 액션 및 getter를 지원합니다. [browserify-hmr](https://github.com/AgentME/browserify-hmr/) 플러그인으로 Browserify에서 사용할 수도 있습니다.
4 |
5 | 변이와 모듈의 경우, `store.hotUpdate()` API 메소드를 사용할 필요가 있습니다.
6 |
7 | ``` js
8 | // store.js
9 | import Vue from 'vue'
10 | import Vuex from 'vuex'
11 | import mutations from './mutations'
12 | import moduleA from './modules/a'
13 |
14 | Vue.use(Vuex)
15 |
16 | const state = { ... }
17 |
18 | const store = new Vuex.Store({
19 | state,
20 | mutations,
21 | modules: {
22 | a: moduleA
23 | }
24 | })
25 |
26 | if (module.hot) {
27 | // 액션과 변이를 핫 모듈로 받아 들인다.
28 | module.hot.accept(['./mutations', './modules/a'], () => {
29 | // 업데이트 된 모듈은 babel 6 모듈 출력으로 인해
30 | // .default를 여기에 추가해야합니다.
31 | const newMutations = require('./mutations').default
32 | const newModuleA = require('./modules/a').default
33 | // 새로운 액션과 변이로 바꿉니다.
34 | store.hotUpdate({
35 | mutations: newMutations,
36 | modules: {
37 | a: newModuleA
38 | }
39 | })
40 | })
41 | }
42 | ```
43 |
44 | [counter-hot 예제](https://github.com/vuejs/vuex/tree/dev/examples/counter-hot)로 핫 리로드를 확인하십시오.
45 |
--------------------------------------------------------------------------------
/docs/en/installation.md:
--------------------------------------------------------------------------------
1 | # Installation
2 |
3 | ### Direct Download / CDN
4 |
5 | [https://unpkg.com/vuex](https://unpkg.com/vuex)
6 |
7 |
8 | [Unpkg.com](https://unpkg.com) provides NPM-based CDN links. The above link will always point to the latest release on NPM. You can also use a specific version/tag via URLs like `https://unpkg.com/vuex@2.0.0`.
9 |
10 |
11 | Include `vuex` after Vue and it will install itself automatically:
12 |
13 | ``` html
14 |
15 |
16 | ```
17 |
18 | ### NPM
19 |
20 | ``` bash
21 | npm install vuex --save
22 | ```
23 |
24 | ### Yarn
25 |
26 | ``` bash
27 | yarn add vuex
28 | ```
29 |
30 | When used with a module system, you must explicitly install Vuex via `Vue.use()`:
31 |
32 | ``` js
33 | import Vue from 'vue'
34 | import Vuex from 'vuex'
35 |
36 | Vue.use(Vuex)
37 | ```
38 |
39 | You don't need to do this when using global script tags.
40 |
41 | ### Dev Build
42 |
43 | You will have to clone directly from GitHub and build `vuex` yourself if
44 | you want to use the latest dev build.
45 |
46 | ``` bash
47 | git clone https://github.com/vuejs/vuex.git node_modules/vuex
48 | cd node_modules/vuex
49 | npm install
50 | npm run build
51 | ```
52 |
--------------------------------------------------------------------------------
/docs/zh-cn/forms.md:
--------------------------------------------------------------------------------
1 | # 表单处理
2 |
3 | 当在严格模式中使用 Vuex 时,在属于 Vuex 的 state 上使用 `v-model` 会比较棘手:
4 |
5 | ``` html
6 |
7 | ```
8 |
9 | 假设这里的 `obj` 是在计算属性中返回的一个属于 Vuex store 的对象,在用户输入时,`v-model` 会试图直接修改 `obj.message`。在严格模式中,由于这个修改不是在 mutation 函数中执行的, 这里会抛出一个错误。
10 |
11 | 用『Vuex 的思维』去解决这个问题的方法是:给 `` 中绑定 value,然后侦听 `input` 或者 `change` 事件,在事件回调中调用 action:
12 |
13 | ``` html
14 |
15 | ```
16 | ``` js
17 | // ...
18 | computed: {
19 | ...mapState({
20 | message: state => state.obj.message
21 | })
22 | },
23 | methods: {
24 | updateMessage (e) {
25 | this.$store.commit('updateMessage', e.target.value)
26 | }
27 | }
28 | ```
29 |
30 | 下面是 mutation 函数:
31 |
32 | ``` js
33 | // ...
34 | mutations: {
35 | updateMessage (state, message) {
36 | state.obj.message = message
37 | }
38 | }
39 | ```
40 |
41 | ### 双向绑定的计算属性
42 |
43 | 必须承认,这样做比简单地使用“`v-model` + 局部状态”要啰嗦得多,并且也损失了一些 `v-model` 中很有用的特性。另一个方法是使用带有 setter 的双向绑定计算属性:
44 |
45 | ``` html
46 |
47 | ```
48 | ``` js
49 | // ...
50 | computed: {
51 | message: {
52 | get () {
53 | return this.$store.state.obj.message
54 | },
55 | set (value) {
56 | this.$store.commit('updateMessage', value)
57 | }
58 | }
59 | }
60 | ```
61 |
--------------------------------------------------------------------------------
/types/test/helpers.ts:
--------------------------------------------------------------------------------
1 | import Vue = require("vue");
2 |
3 | import {
4 | mapState,
5 | mapGetters,
6 | mapActions,
7 | mapMutations
8 | } from "../index";
9 |
10 | new Vue({
11 | computed: Object.assign({},
12 | mapState(["a"]),
13 | mapState('foo', ["a"]),
14 | mapState({
15 | b: "b"
16 | }),
17 | mapState('foo', {
18 | b: "b"
19 | }),
20 | mapState({
21 | c: (state: any, getters: any) => state.c + getters.c
22 | }),
23 | mapState('foo', {
24 | c: (state: any, getters: any) => state.c + getters.c
25 | }),
26 |
27 | mapGetters(["d"]),
28 | mapGetters('foo', ["d"]),
29 | mapGetters({
30 | e: "e"
31 | }),
32 | mapGetters('foo', {
33 | e: "e"
34 | }),
35 |
36 | {
37 | otherComputed () {
38 | return "f";
39 | }
40 | }
41 | ),
42 |
43 | methods: Object.assign({},
44 | mapActions(["g"]),
45 | mapActions({
46 | h: "h"
47 | }),
48 | mapActions('foo', ["g"]),
49 | mapActions('foo', {
50 | h: "h"
51 | }),
52 |
53 | mapMutations(["i"]),
54 | mapMutations({
55 | j: "j"
56 | }),
57 | mapMutations('foo', ["i"]),
58 | mapMutations('foo', {
59 | j: "j"
60 | }),
61 |
62 | {
63 | otherMethod () {}
64 | }
65 | )
66 | });
67 |
--------------------------------------------------------------------------------
/docs/en/structure.md:
--------------------------------------------------------------------------------
1 | # Application Structure
2 |
3 | Vuex doesn't really restrict how you structure your code. Rather, it enforces a set of high-level principles:
4 |
5 | 1. Application-level state is centralized in the store.
6 |
7 | 2. The only way to mutate the state is by committing **mutations**, which are synchronous transactions.
8 |
9 | 3. Asynchronous logic should be encapsulated in, and can be composed with **actions**.
10 |
11 | As long as you follow these rules, it's up to you how to structure your project. If your store file gets too big, simply start splitting the actions, mutations and getters into separate files.
12 |
13 | For any non-trivial app, we will likely need to leverage modules. Here's an example project structure:
14 |
15 | ``` bash
16 | ├── index.html
17 | ├── main.js
18 | ├── api
19 | │ └── ... # abstractions for making API requests
20 | ├── components
21 | │ ├── App.vue
22 | │ └── ...
23 | └── store
24 | ├── index.js # where we assemble modules and export the store
25 | ├── actions.js # root actions
26 | ├── mutations.js # root mutations
27 | └── modules
28 | ├── cart.js # cart module
29 | └── products.js # products module
30 | ```
31 |
32 | As a reference, check out the [Shopping Cart Example](https://github.com/vuejs/vuex/tree/dev/examples/shopping-cart).
33 |
--------------------------------------------------------------------------------
/test/e2e/nightwatch.config.js:
--------------------------------------------------------------------------------
1 | // http://nightwatchjs.org/guide#settings-file
2 | module.exports = {
3 | 'src_folders': ['test/e2e/specs'],
4 | 'output_folder': 'test/e2e/reports',
5 | 'custom_commands_path': ['node_modules/nightwatch-helpers/commands'],
6 | 'custom_assertions_path': ['node_modules/nightwatch-helpers/assertions'],
7 |
8 | 'selenium': {
9 | 'start_process': true,
10 | 'server_path': require('selenium-server').path,
11 | 'host': '127.0.0.1',
12 | 'port': 4444,
13 | 'cli_args': {
14 | 'webdriver.chrome.driver': require('chromedriver').path
15 | }
16 | },
17 |
18 | 'test_settings': {
19 | 'default': {
20 | 'selenium_port': 4444,
21 | 'selenium_host': 'localhost',
22 | 'silent': true,
23 | 'screenshots': {
24 | 'enabled': true,
25 | 'on_failure': true,
26 | 'on_error': false,
27 | 'path': 'test/e2e/screenshots'
28 | }
29 | },
30 |
31 | 'chrome': {
32 | 'desiredCapabilities': {
33 | 'browserName': 'chrome',
34 | 'javascriptEnabled': true,
35 | 'acceptSslCerts': true
36 | }
37 | },
38 |
39 | 'phantomjs': {
40 | 'desiredCapabilities': {
41 | 'browserName': 'phantomjs',
42 | 'javascriptEnabled': true,
43 | 'acceptSslCerts': true
44 | }
45 | }
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/docs/kr/forms.md:
--------------------------------------------------------------------------------
1 | # 폼 핸들링
2 |
3 | strict 모드로 Vuex를 사용하는 경우 Vuex에 포함된 부분에 `v-model`을 사용하는 것은 약간 까다로울 수 있습니다.
4 |
5 | ``` html
6 |
7 | ```
8 |
9 | `obj`가 저장소에서 객체를 반환하는 계산된 속성이라면, 여기에있는 `v-model`은 사용자가 입력 할 때 `obj.message`를 직접 변경하려고 합니다. strict 모드에서는 Vuex 변이 처리기 내부에서 변이가 수행되지 않으므로 오류가 발생합니다.
10 |
11 | 그것을 다루는 "Vuex 방식"은 ``의 값을 바인딩하고 `input` 또는 `change` 이벤트에 대한 액션을 호출하는 것 입니다.
12 |
13 | ``` html
14 |
15 | ```
16 | ``` js
17 | // ...
18 | computed: {
19 | ...mapState({
20 | message: state => state.obj.message
21 | })
22 | },
23 | methods: {
24 | updateMessage (e) {
25 | this.$store.commit('updateMessage', e.target.value)
26 | }
27 | }
28 | ```
29 |
30 | 변이에 대한 핸들러 입니다.
31 |
32 | ``` js
33 | // ...
34 | mutations: {
35 | updateMessage (state, message) {
36 | state.obj.message = message
37 | }
38 | }
39 | ```
40 |
41 | ### 양방향 계산된 속성
42 |
43 | 틀림없이, 위의 내용은 `v-model` + 지역 상태보다 좀더 장황 해졌고, `v-model`의 유용한 기능 중 일부를 잃어 버렸습니다. 다른 방법은 setter를 사용하여 양방향 계산된 속성을 사용하는 것입니다.
44 |
45 | ``` html
46 |
47 | ```
48 | ``` js
49 | // ...
50 | computed: {
51 | message: {
52 | get () {
53 | return this.$store.state.obj.message
54 | },
55 | set (value) {
56 | this.$store.commit('updateMessage', value)
57 | }
58 | }
59 | }
60 | ```
61 |
--------------------------------------------------------------------------------
/docs/ja/hot-reload.md:
--------------------------------------------------------------------------------
1 | # ホットリローディング
2 |
3 | Vuex は Webpack の [Hot Module Replacement API](https://webpack.github.io/docs/hot-module-replacement.html) を使用することで、アプリケーションの開発を行っている間のミューテーション、モジュール、アクション、ゲッターのホットリローディングをサポートします。Browserify では [browserify-hmr](https://github.com/AgentME/browserify-hmr/) プラグインを使用することができます。
4 |
5 | ミューテーションとモジュールのホットリローディングのために、`store.hotUpdate()` API メソッドを利用する必要があります:
6 |
7 | ``` js
8 | // store.js
9 | import Vue from 'vue'
10 | import Vuex from 'vuex'
11 | import mutations from './mutations'
12 | import moduleA from './modules/a'
13 |
14 | Vue.use(Vuex)
15 |
16 | const state = { ... }
17 |
18 | const store = new Vuex.Store({
19 | state,
20 | mutations,
21 | modules: {
22 | a: moduleA
23 | }
24 | })
25 |
26 | if (module.hot) {
27 | // ホットモジュールとしてアクションとモジュールを受け付けます
28 | module.hot.accept(['./mutations', './modules/a'], () => {
29 | // 更新されたモジュールをインポートする
30 | // babel 6 のモジュール出力のため、ここでは .default を追加しなければならない
31 | const newActions = require('./actions').default
32 | const newMutations = require('./mutations').default
33 | // 新しいアクションとミューテーションにスワップ
34 | store.hotUpdate({
35 | mutations: newMutations,
36 | modules: {
37 | a: newModuleA
38 | }
39 | })
40 | })
41 | }
42 | ```
43 |
44 | ホットリローディングを試したい場合は、[counter-hot example](https://github.com/vuejs/vuex/tree/dev/examples/counter-hot)をチェックアウトしてください。
--------------------------------------------------------------------------------
/docs/ja/forms.md:
--------------------------------------------------------------------------------
1 | # フォームの扱い
2 |
3 | 厳格モードで Vuex を使用するとき、Vuex に属する状態の一部で `v-model` を使用するのは少しトリッキーです:
4 |
5 | ``` html
6 |
7 | ```
8 |
9 | `obj` がストアからオブジェクトを返す算出プロパティ (computed property) と仮定すると、`v-model` は input でユーザーが入力するとき、直接 `obj.message` を変更します。厳格モードでは、この変更は明示的に Vuex のミューテーションハンドラ内部で処理されていないため、エラーを投げます。
10 |
11 | それに対処するための "Vuex way" は、`` の値をバインディングし、`input` または `change` イベントでアクションを呼び出すことです:
12 |
13 | ``` html
14 |
15 | ```
16 | ``` js
17 | // ...
18 | computed: {
19 | ...mapState({
20 | message: state => state.obj.message
21 | })
22 | },
23 | methods: {
24 | updateMessage: ({ dispatch }, e) => {
25 | this.$store.commit('updateMessage', e.target.value)
26 | }
27 | }
28 | ```
29 |
30 | ミューテーションのハンドラは以下のようになります:
31 |
32 | ``` js
33 | // ...
34 | mutations: {
35 | updateMessage (state, message) {
36 | state.obj.message = message
37 | }
38 | }
39 | ```
40 |
41 | ### 双方向算出プロパティ
42 |
43 | 確かに、上記の例は単純な `v-model` と ローカルステートよりもかなり冗長で、`v-model` のいくつかの有用な機能が使えません。代わりに、セッターで双方向算出プロパティを使うアプローチがあります。
44 |
45 | ``` html
46 |
47 | ```
48 | ``` js
49 | computed: {
50 | message: {
51 | get () {
52 | return this.$store.state.obj.message
53 | },
54 | set (value) {
55 | this.$store.commit('updateMessage', value)
56 | }
57 | }
58 | }
59 | ```
60 |
--------------------------------------------------------------------------------
/docs/fr/installation.md:
--------------------------------------------------------------------------------
1 | # Installation
2 |
3 | ### Téléchargement direct / CDN
4 |
5 | [https://unpkg.com/vuex](https://unpkg.com/vuex)
6 |
7 |
8 | [Unpkg.com](https://unpkg.com) fournit des liens CDN basés sur NPM. Le lien ci-dessus pointera toujours vers la dernière release sur NPM. Vous pouvez aussi utiliser un tag ou une version spécifique comme `https://unpkg.com/vuex@2.0.0`.
9 |
10 |
11 | Incluez `vuex` après Vue et l'installation sera automatique :
12 |
13 | ``` html
14 |
15 |
16 | ```
17 |
18 | ### NPM
19 |
20 | ``` bash
21 | npm install vuex --save
22 | ```
23 |
24 | ### Yarn
25 |
26 | ``` bash
27 | yarn add vuex
28 | ```
29 |
30 | Lorsque vous utilisez un système de modules, vous devez explicitement installer le router via `Vue.use()`:
31 |
32 | ``` js
33 | import Vue from 'vue'
34 | import Vuex from 'vuex'
35 |
36 | Vue.use(Vuex)
37 | ```
38 |
39 | Il n'est pas nécessaire de faire ceci lorsque vous utilisez des balises de script globales.
40 |
41 | ### Environnement de dev
42 |
43 | Vous devrez cloner directement depuis GitHub et compiler `vuex` vous-même si
44 | vous souhaitez utiliser la dernière version de dev.
45 |
46 | ``` bash
47 | git clone https://github.com/vuejs/vuex.git node_modules/vuex
48 | cd node_modules/vuex
49 | npm install
50 | npm run build
51 | ```
52 |
--------------------------------------------------------------------------------
/docs/ru/installation.md:
--------------------------------------------------------------------------------
1 | # Установка
2 |
3 | ### Скачать напрямую или использовать CDN
4 |
5 | [https://unpkg.com/vuex](https://unpkg.com/vuex)
6 |
7 |
8 | [Unpkg.com](https://unpkg.com) предоставляет CDN-ссылки на содержимое NPM-пакетов. Приведённая выше ссылка всегда будет указывать на самый свежий релиз Vuex, доступный в NPM. Кроме того, можно указать конкретную версию или тег, например `https://unpkg.com/vuex@2.0.0`.
9 |
10 |
11 | Подключите `vuex` после Vue, и установка произойдёт автоматически:
12 |
13 | ``` html
14 |
15 |
16 | ```
17 |
18 | ### NPM
19 |
20 | ``` bash
21 | npm install vuex --save
22 | ```
23 |
24 | ### Yarn
25 |
26 | ``` bash
27 | yarn add vuex
28 | ```
29 |
30 | Если вы используете модули, установите Vuex явным образом командой `Vue.use()`:
31 |
32 | ``` js
33 | import Vue from 'vue'
34 | import Vuex from 'vuex'
35 |
36 | Vue.use(Vuex)
37 | ```
38 |
39 | При использовании глобальных тегов `
55 |
--------------------------------------------------------------------------------
/docs/en/hot-reload.md:
--------------------------------------------------------------------------------
1 | # Hot Reloading
2 |
3 | Vuex supports hot-reloading mutations, modules, actions and getters during development, using Webpack's [Hot Module Replacement API](https://webpack.github.io/docs/hot-module-replacement.html). You can also use it in Browserify with the [browserify-hmr](https://github.com/AgentME/browserify-hmr/) plugin.
4 |
5 | For mutations and modules, you need to use the `store.hotUpdate()` API method:
6 |
7 | ``` js
8 | // store.js
9 | import Vue from 'vue'
10 | import Vuex from 'vuex'
11 | import mutations from './mutations'
12 | import moduleA from './modules/a'
13 |
14 | Vue.use(Vuex)
15 |
16 | const state = { ... }
17 |
18 | const store = new Vuex.Store({
19 | state,
20 | mutations,
21 | modules: {
22 | a: moduleA
23 | }
24 | })
25 |
26 | if (module.hot) {
27 | // accept actions and mutations as hot modules
28 | module.hot.accept(['./mutations', './modules/a'], () => {
29 | // require the updated modules
30 | // have to add .default here due to babel 6 module output
31 | const newMutations = require('./mutations').default
32 | const newModuleA = require('./modules/a').default
33 | // swap in the new actions and mutations
34 | store.hotUpdate({
35 | mutations: newMutations,
36 | modules: {
37 | a: newModuleA
38 | }
39 | })
40 | })
41 | }
42 | ```
43 |
44 | Checkout the [counter-hot example](https://github.com/vuejs/vuex/tree/dev/examples/counter-hot) to play with hot-reload.
45 |
--------------------------------------------------------------------------------
/docs/ru/structure.md:
--------------------------------------------------------------------------------
1 | # Структура приложения
2 |
3 | В действительности Vuex не накладывает каких-то значительных ограничений на используемую структуру кода. Однако, он требует соблюдения нескольких высокоуровневых принципов:
4 |
5 | 1. Глобальное состояние приложения должно содержаться в централизованном хранилище;
6 |
7 | 2. Единственным механизмом изменения этого состояния являются **мутации**, являющиеся синхронными транзакциями;
8 |
9 | 3. Асинхронные операции инкапсулирутся в **действия**, или их комбинации.
10 |
11 | Покуда вы следуете этим правилам, можно использовать любую структуру проекта. Если ваш файл хранилища становится слишком большим, просто начните выносить действия, мутации и геттеры в отдельные файлы.
12 |
13 | Для любого нетривиального приложения скорее всего понадобится использование модулей. Вот пример возможной структуры проекта:
14 |
15 | ``` bash
16 | ├── index.html
17 | ├── main.js
18 | ├── api
19 | │ └── ... # абстракции для выполнения запросов к API
20 | ├── components
21 | │ ├── App.vue
22 | │ └── ...
23 | └── store
24 | ├── index.js # здесь мы собираем модули и экспортируем хранилище
25 | ├── actions.js # корневые действия
26 | ├── mutations.js # корневые мутации
27 | └── modules
28 | ├── cart.js # модуль корзины
29 | └── products.js # модуль товаров
30 | ```
31 |
32 | Для справки можно использовать [Пример корзины покупок](https://github.com/vuejs/vuex/tree/dev/examples/shopping-cart).
33 |
--------------------------------------------------------------------------------
/docs/kr/getting-started.md:
--------------------------------------------------------------------------------
1 | # 시작하기
2 |
3 | 모든 Vuex 애플리케이션의 중심에는 **store** 가 있습니다. "저장소"는 기본적으로 애플리케이션 **상태** 를 보유하고있는 컨테이너입니다. Vuex 저장소가 일반 전역 개체와 두 가지 다른 점이 있습니다.
4 |
5 | 1. Vuex store는 반응형 입니다. Vue 컴포넌트는 상태를 검색할 때 저장소의 상태가 변경되면 효율적으로 대응하고 업데이트합니다.
6 | 2. 저장소의 상태를 직접 변경할 수 없습니다. 저장소의 상태를 변경하는 유일한 방법은 명시적인 **커밋을 이용한 변이** 입니다. 이렇게하면 모든 상태에 대한 추적이 가능한 기록이 남을 수 있으며 툴를 사용하여 앱을 더 잘 이해할 수 있습니다.
7 |
8 | ### 가장 단순한 저장소
9 |
10 | > **참고:** 모든 예제는 ES2015 문법을 사용합니다. 사용하고 있지 않은 경우 [꼭 사용해야 합니다!](https://babeljs.io/docs/learn-es2015/)
11 |
12 | Vuex를 [설치](installation.md)한 후 저장소를 만들어 봅시다. 매우 간단합니다. 초기 상태 객체와 일부 변이를 제공하십시오.
13 |
14 | ``` js
15 | // 모듈 시스템을 사용하는 경우 Vue.use(Vuex)를 먼저 호출해야합니다.
16 |
17 | const store = new Vuex.Store({
18 | state: {
19 | count: 0
20 | },
21 | mutations: {
22 | increment (state) {
23 | state.count++
24 | }
25 | }
26 | })
27 | ```
28 |
29 | 이제 state 객체에 `store.state`로 접근하여 `store.commit` 메소드로 상태 변경을 트리거 할 수 있습니다.
30 |
31 | ``` js
32 | store.commit('increment')
33 |
34 | console.log(store.state.count) // -> 1
35 | ```
36 |
37 | 다시 말해, `store.state.count`를 직접 변경하는 대신 변이를 수행하는 이유는 명시적으로 추적을 하기 때문입니다. 이 간단한 규칙에 따라 의도를보다 명확하게 표현할 수 있으므로 코드를 읽을 때 상태 변화를 더 잘 지켜볼 수 있습니다. 또한 모든 변이를 기록하고 상태 스냅샷을 저장하거나 시간 흐름에 따라 디버깅을 할 수 있는 도구를 제공합니다.
38 |
39 | 컴포넌트 안에서 저장소 상태를 사용하는 것은 단순히 계산된 속성 내에서 상태를 반환하는 것입니다. 변경을 트리거하는 것은 컴포넌트 메소드에서 변경을 커밋하는 것을 의미합니다.
40 |
41 | 다음은 [가장 기본적인 Vuex 카운터 앱](https://jsfiddle.net/n9jmu5v7/341/)의 예입니다.
42 |
43 | 이제, 우리는 각 핵심 개념에 대해 더 자세히 설명 할 것입니다. [State](state.md)부터 시작해 보겠습니다.
44 |
--------------------------------------------------------------------------------
/docs/ru/hot-reload.md:
--------------------------------------------------------------------------------
1 | # Горячая замена
2 |
3 | Vuex поддерживает горячую замену мутаций, модулей, действий и геттеров в момент разработки с помощью [Webpack Hot Module Replacement API](https://webpack.github.io/docs/hot-module-replacement.html). Аналогичный функционал в Browserify достижим при использовании плагина [browserify-hmr](https://github.com/AgentME/browserify-hmr/).
4 |
5 | Для мутаций и модулей необходимо использовать метод API `store.hotUpdate()`:
6 |
7 | ``` js
8 | // store.js
9 | import Vue from 'vue'
10 | import Vuex from 'vuex'
11 | import mutations from './mutations'
12 | import moduleA from './modules/a'
13 |
14 | Vue.use(Vuex)
15 |
16 | const state = { ... }
17 |
18 | const store = new Vuex.Store({
19 | state,
20 | mutations,
21 | modules: {
22 | a: moduleA
23 | }
24 | })
25 |
26 | if (module.hot) {
27 | // рассматриваем действия и мутации как модули для горячей замены
28 | module.hot.accept(['./mutations', './modules/a'], () => {
29 | // запрашиваем обновлённые модули
30 | // (нужно указать .default из-за формата вывода Babel 6)
31 | const newMutations = require('./mutations').default
32 | const newModuleA = require('./modules/a').default
33 | // заменяем старые действия и мутации новыми
34 | store.hotUpdate({
35 | mutations: newMutations,
36 | modules: {
37 | a: newModuleA
38 | }
39 | })
40 | })
41 | }
42 | ```
43 |
44 | [Пример counter-hot](https://github.com/vuejs/vuex/tree/dev/examples/counter-hot) позволяет посмотреть на горячую замену в реальной жизни.
45 |
--------------------------------------------------------------------------------
/test/e2e/specs/chat.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | 'chat': function (browser) {
3 | browser
4 | .url('http://localhost:8080/chat/')
5 | .waitForElementVisible('.chatapp', 1000)
6 | .assert.containsText('.thread-count', 'Unread threads: 2')
7 | .assert.count('.thread-list-item', 3)
8 | .assert.containsText('.thread-list-item.active', 'Functional Heads')
9 | .assert.containsText('.message-thread-heading', 'Functional Heads')
10 | .assert.count('.message-list-item', 2)
11 | .assert.containsText('.message-list-item:nth-child(1) .message-author-name', 'Bill')
12 | .assert.containsText('.message-list-item:nth-child(1) .message-text', 'Hey Brian')
13 | .enterValue('.message-composer', 'hi')
14 | .waitFor(50) // fake api
15 | .assert.count('.message-list-item', 3)
16 | .assert.containsText('.message-list-item:nth-child(3)', 'hi')
17 | .click('.thread-list-item:nth-child(2)')
18 | .assert.containsText('.thread-list-item.active', 'Dave and Bill')
19 | .assert.containsText('.message-thread-heading', 'Dave and Bill')
20 | .assert.count('.message-list-item', 2)
21 | .assert.containsText('.message-list-item:nth-child(1) .message-author-name', 'Bill')
22 | .assert.containsText('.message-list-item:nth-child(1) .message-text', 'Hey Dave')
23 | .enterValue('.message-composer', 'hi')
24 | .waitFor(50) // fake api
25 | .assert.count('.message-list-item', 3)
26 | .assert.containsText('.message-list-item:nth-child(3)', 'hi')
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/docs/fr/hot-reload.md:
--------------------------------------------------------------------------------
1 | # Hot Reloading
2 |
3 | Vuex prend en charge le `hot-reloading` des mutations, modules, actions et getters durant le développement, en utilisant l'[API Hot Module Replacement](https://webpack.github.io/docs/hot-module-replacement.html) de Webpack. Vous pouvez également utiliser Browserify avec le plugin [browserify-hmr](https://github.com/AgentME/browserify-hmr/).
4 |
5 | Pour les mutations et les modules, vous aurez besoin d'utiliser la méthode d'API `store.hotUpdate()` :
6 |
7 | ``` js
8 | // store.js
9 | import Vue from 'vue'
10 | import Vuex from 'vuex'
11 | import mutations from './mutations'
12 | import moduleA from './modules/a'
13 |
14 | Vue.use(Vuex)
15 |
16 | const state = { ... }
17 |
18 | const store = new Vuex.Store({
19 | state,
20 | mutations,
21 | modules: {
22 | a: moduleA
23 | }
24 | })
25 |
26 | if (module.hot) {
27 | // accept actions and mutations as hot modules
28 | module.hot.accept(['./mutations', './modules/a'], () => {
29 | // require the updated modules
30 | // have to add .default here due to babel 6 module output
31 | const newMutations = require('./mutations').default
32 | const newModuleA = require('./modules/a').default
33 | // swap in the new actions and mutations
34 | store.hotUpdate({
35 | mutations: newMutations,
36 | modules: {
37 | a: newModuleA
38 | }
39 | })
40 | })
41 | }
42 | ```
43 |
44 | Jetez un œil à [l'exemple counter-hot](https://github.com/vuejs/vuex/tree/dev/examples/counter-hot) pour jouer avec le hot-reload.
45 |
--------------------------------------------------------------------------------
/src/module/module.js:
--------------------------------------------------------------------------------
1 | import { forEachValue } from '../util'
2 |
3 | export default class Module {
4 | constructor (rawModule, runtime) {
5 | this.runtime = runtime
6 | this._children = Object.create(null)
7 | this._rawModule = rawModule
8 | }
9 |
10 | get state () {
11 | return this._rawModule.state || {}
12 | }
13 |
14 | get namespaced () {
15 | return !!this._rawModule.namespaced
16 | }
17 |
18 | addChild (key, module) {
19 | this._children[key] = module
20 | }
21 |
22 | removeChild (key) {
23 | delete this._children[key]
24 | }
25 |
26 | getChild (key) {
27 | return this._children[key]
28 | }
29 |
30 | update (rawModule) {
31 | this._rawModule.namespaced = rawModule.namespaced
32 | if (rawModule.actions) {
33 | this._rawModule.actions = rawModule.actions
34 | }
35 | if (rawModule.mutations) {
36 | this._rawModule.mutations = rawModule.mutations
37 | }
38 | if (rawModule.getters) {
39 | this._rawModule.getters = rawModule.getters
40 | }
41 | }
42 |
43 | forEachChild (fn) {
44 | forEachValue(this._children, fn)
45 | }
46 |
47 | forEachGetter (fn) {
48 | if (this._rawModule.getters) {
49 | forEachValue(this._rawModule.getters, fn)
50 | }
51 | }
52 |
53 | forEachAction (fn) {
54 | if (this._rawModule.actions) {
55 | forEachValue(this._rawModule.actions, fn)
56 | }
57 | }
58 |
59 | forEachMutation (fn) {
60 | if (this._rawModule.mutations) {
61 | forEachValue(this._rawModule.mutations, fn)
62 | }
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/examples/counter/store.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import Vuex from 'vuex'
3 |
4 | Vue.use(Vuex)
5 |
6 | // root state object.
7 | // each Vuex instance is just a single state tree.
8 | const state = {
9 | count: 0
10 | }
11 |
12 | // mutations are operations that actually mutates the state.
13 | // each mutation handler gets the entire state tree as the
14 | // first argument, followed by additional payload arguments.
15 | // mutations must be synchronous and can be recorded by plugins
16 | // for debugging purposes.
17 | const mutations = {
18 | increment (state) {
19 | state.count++
20 | },
21 | decrement (state) {
22 | state.count--
23 | }
24 | }
25 |
26 | // actions are functions that causes side effects and can involve
27 | // asynchronous operations.
28 | const actions = {
29 | increment: ({ commit }) => commit('increment'),
30 | decrement: ({ commit }) => commit('decrement'),
31 | incrementIfOdd ({ commit, state }) {
32 | if ((state.count + 1) % 2 === 0) {
33 | commit('increment')
34 | }
35 | },
36 | incrementAsync ({ commit }) {
37 | return new Promise((resolve, reject) => {
38 | setTimeout(() => {
39 | commit('increment')
40 | resolve()
41 | }, 1000)
42 | })
43 | }
44 | }
45 |
46 | // getters are functions
47 | const getters = {
48 | evenOrOdd: state => state.count % 2 === 0 ? 'even' : 'odd'
49 | }
50 |
51 | // A Vuex instance is created by combining the state, mutations, actions,
52 | // and getters.
53 | export default new Vuex.Store({
54 | state,
55 | getters,
56 | actions,
57 | mutations
58 | })
59 |
--------------------------------------------------------------------------------
/docs/ja/getting-started.md:
--------------------------------------------------------------------------------
1 | # Vuex 入門
2 |
3 | Vuex アプリケーションの中心にあるものは**ストア**です。"ストア" は、基本的にアプリケーションの**状態(state)**を保持するコンテナです。単純なグローバルオブジェクトとの違いが 2つあります。
4 |
5 | 1. Vuex ストアはリアクティブです。Vue コンポーネントがストアから状態を取り出すとき、もしストアの状態が変化したら、ストアはリアクティブかつ効率的に更新を行います。
6 |
7 | 2. ストアの状態を直接変更することはできません。明示的に**ミューテーションをコミットする**ことによってのみ、ストアの状態を変更します。これによって、全ての状態の変更について追跡可能な記録を残すことが保証され、ツールでのアプリケーションの動作の理解を助けます。
8 |
9 | ### シンプルなストア
10 |
11 | > **注意:** 私たちは、このドキュメントのコード例に ES2015 のシンタックスを利用しています。 もし触れたことがなければ、[ぜひ触れてください](https://babeljs.io/docs/learn-es2015/)!
12 |
13 | Vuex を[インストール](installation.md) してから、ストアをつくってみましょう。Vuex ストアの作成は、とても簡単です。ストアオブジェクトの初期状態と、いくつかのミューテーションを準備するだけです。
14 |
15 | ``` js
16 | // モジュールシステムを利用しているときはあらかじめ Vue.use(Vuex) を呼び出していることを確認しておいてください
17 |
18 | const store = new Vuex.Store({
19 | state: {
20 | count: 0
21 | },
22 | mutations: {
23 | increment (state) {
24 | state.count++
25 | }
26 | }
27 | })
28 | ```
29 |
30 | これで `store.state` でストアオブジェクトの状態を参照でき、また `store.commit` メソッドで状態の変更を行うことができます。
31 |
32 | ``` js
33 | store.commit('increment')
34 |
35 | console.log(store.state.count) // -> 1
36 | ```
37 |
38 | そして `store.state.count` を直接変更する代わりにミューテーションをコミットする理由は、状態の変更を明確に追跡したいからです。このシンプルな規約は、あなたのコードの意図をさらに明確にし、コードを読んだ時にアプリケーションの状態の変更について、論理的に考えることができるようにします。加えて、私たちに全ての変更のログを取ったり、状態のスナップショットを取ったり、タイムトラベルデバッグを行うようなツールを実装する余地を与えてくれます。
39 |
40 | ストアオブジェクトの状態はリアクティブなので、ストアの状態をコンポーネント内で使うには算出プロパティ内でただ状態を返せば良いです。コンポーネントメソッドでミューテーションをコミットすることによって状態の変更を行います。
41 |
42 | こちらが [Vuex を使った最も基本的なカウンターアプリの例](https://jsfiddle.net/n9jmu5v7/341/)です。
43 |
44 | これから Vuex のコアコンセプトについて詳しく説明していきます。まずは[状態(state)](state.md)からはじめましょう。
45 |
--------------------------------------------------------------------------------
/examples/shopping-cart/store/modules/cart.js:
--------------------------------------------------------------------------------
1 | import shop from '../../api/shop'
2 | import * as types from '../mutation-types'
3 |
4 | // initial state
5 | // shape: [{ id, quantity }]
6 | const state = {
7 | added: [],
8 | checkoutStatus: null
9 | }
10 |
11 | // getters
12 | const getters = {
13 | checkoutStatus: state => state.checkoutStatus
14 | }
15 |
16 | // actions
17 | const actions = {
18 | checkout ({ commit, state }, products) {
19 | const savedCartItems = [...state.added]
20 | commit(types.CHECKOUT_REQUEST)
21 | shop.buyProducts(
22 | products,
23 | () => commit(types.CHECKOUT_SUCCESS),
24 | () => commit(types.CHECKOUT_FAILURE, { savedCartItems })
25 | )
26 | }
27 | }
28 |
29 | // mutations
30 | const mutations = {
31 | [types.ADD_TO_CART] (state, { id }) {
32 | state.lastCheckout = null
33 | const record = state.added.find(p => p.id === id)
34 | if (!record) {
35 | state.added.push({
36 | id,
37 | quantity: 1
38 | })
39 | } else {
40 | record.quantity++
41 | }
42 | },
43 |
44 | [types.CHECKOUT_REQUEST] (state) {
45 | // clear cart
46 | state.added = []
47 | state.checkoutStatus = null
48 | },
49 |
50 | [types.CHECKOUT_SUCCESS] (state) {
51 | state.checkoutStatus = 'successful'
52 | },
53 |
54 | [types.CHECKOUT_FAILURE] (state, { savedCartItems }) {
55 | // rollback to the cart saved before sending the request
56 | state.added = savedCartItems
57 | state.checkoutStatus = 'failed'
58 | }
59 | }
60 |
61 | export default {
62 | state,
63 | getters,
64 | actions,
65 | mutations
66 | }
67 |
--------------------------------------------------------------------------------
/examples/chat/api/mock-data.js:
--------------------------------------------------------------------------------
1 | module.exports = [
2 | {
3 | id: 'm_1',
4 | threadID: 't_1',
5 | threadName: 'Jing and Bill',
6 | authorName: 'Bill',
7 | text: 'Hey Jing, want to give a Flux talk at ForwardJS?',
8 | timestamp: Date.now() - 99999
9 | },
10 | {
11 | id: 'm_2',
12 | threadID: 't_1',
13 | threadName: 'Jing and Bill',
14 | authorName: 'Bill',
15 | text: 'Seems like a pretty cool conference.',
16 | timestamp: Date.now() - 89999
17 | },
18 | {
19 | id: 'm_3',
20 | threadID: 't_1',
21 | threadName: 'Jing and Bill',
22 | authorName: 'Jing',
23 | text: 'Sounds good. Will they be serving dessert?',
24 | timestamp: Date.now() - 79999
25 | },
26 | {
27 | id: 'm_4',
28 | threadID: 't_2',
29 | threadName: 'Dave and Bill',
30 | authorName: 'Bill',
31 | text: 'Hey Dave, want to get a beer after the conference?',
32 | timestamp: Date.now() - 69999
33 | },
34 | {
35 | id: 'm_5',
36 | threadID: 't_2',
37 | threadName: 'Dave and Bill',
38 | authorName: 'Dave',
39 | text: 'Totally! Meet you at the hotel bar.',
40 | timestamp: Date.now() - 59999
41 | },
42 | {
43 | id: 'm_6',
44 | threadID: 't_3',
45 | threadName: 'Functional Heads',
46 | authorName: 'Bill',
47 | text: 'Hey Brian, are you going to be talking about functional stuff?',
48 | timestamp: Date.now() - 49999
49 | },
50 | {
51 | id: 'm_7',
52 | threadID: 't_3',
53 | threadName: 'Bill and Brian',
54 | authorName: 'Brian',
55 | text: 'At ForwardJS? Yeah, of course. See you there!',
56 | timestamp: Date.now() - 39999
57 | }
58 | ]
59 |
--------------------------------------------------------------------------------
/docs/en/forms.md:
--------------------------------------------------------------------------------
1 | # Form Handling
2 |
3 | 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:
4 |
5 | ``` html
6 |
7 | ```
8 |
9 | Assuming `obj` is a computed property that returns an Object from the store, the `v-model` here will attempt to directly mutate `obj.message` when the user types in the input. In strict mode, this will result in an error because the mutation is not performed inside an explicit Vuex mutation handler.
10 |
11 | The "Vuex way" to deal with it is binding the ``'s value and call an action on the `input` or `change` event:
12 |
13 | ``` html
14 |
15 | ```
16 | ``` js
17 | // ...
18 | computed: {
19 | ...mapState({
20 | message: state => state.obj.message
21 | })
22 | },
23 | methods: {
24 | updateMessage (e) {
25 | this.$store.commit('updateMessage', e.target.value)
26 | }
27 | }
28 | ```
29 |
30 | And here's the mutation handler:
31 |
32 | ``` js
33 | // ...
34 | mutations: {
35 | updateMessage (state, message) {
36 | state.obj.message = message
37 | }
38 | }
39 | ```
40 |
41 | ### Two-way Computed Property
42 |
43 | Admittedly, the above is quite a bit more verbose than `v-model` + local state, and we lose some of the useful features from `v-model` as well. An alternative approach is using a two-way computed property with a setter:
44 |
45 | ``` html
46 |
47 | ```
48 | ``` js
49 | // ...
50 | computed: {
51 | message: {
52 | get () {
53 | return this.$store.state.obj.message
54 | },
55 | set (value) {
56 | this.$store.commit('updateMessage', value)
57 | }
58 | }
59 | }
60 | ```
61 |
62 |
--------------------------------------------------------------------------------
/src/util.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Get the first item that pass the test
3 | * by second argument function
4 | *
5 | * @param {Array} list
6 | * @param {Function} f
7 | * @return {*}
8 | */
9 | function find (list, f) {
10 | return list.filter(f)[0]
11 | }
12 |
13 | /**
14 | * Deep copy the given object considering circular structure.
15 | * This function caches all nested objects and its copies.
16 | * If it detects circular structure, use cached copy to avoid infinite loop.
17 | *
18 | * @param {*} obj
19 | * @param {Array