Evan You пре 8 година
родитељ
комит
6b9295a975
10 измењених фајлова са 162 додато и 239 уклоњено
  1. 2 1
      docs/LANGS.md
  2. 4 4
      docs/en/SUMMARY.md
  3. 0 89
      docs/en/data-flow.md
  4. 77 0
      docs/en/getters.md
  5. 17 30
      docs/en/getting-started.md
  6. 0 0
      docs/en/modules.md
  7. 0 2
      docs/en/mutations.md
  8. 54 113
      docs/en/state.md
  9. 8 0
      docs/old/README.md
  10. 0 0
      docs/old/SUMMARY.md

+ 2 - 1
docs/LANGS.md

@@ -1 +1,2 @@
-* [English](en/)
+* [2.0 - English](en/)
+* [1.0 Docs](old/)

+ 4 - 4
docs/en/SUMMARY.md

@@ -1,18 +1,18 @@
 # Vuex
 
-### Large-scale State Management for Vue.js
-
-> Note: This is docs for vuex@2.x. The docs for 1.x is [here](https://github.com/vuejs/vuex/tree/1.0/docs).
+> Note: This is docs for vuex@2.x.
 
+- [Looking for 1.0 Docs?](https://github.com/vuejs/vuex/tree/1.0/docs)
 - [Release Notes](https://github.com/vuejs/vuex/releases)
 - [Installation](installation.md)
 - [What is Vuex?](intro.md)
 - [Getting Started](getting-started.md)
 - Core Concepts
   - [State](state.md)
+  - [Getters](getters.md)
   - [Mutations](mutations.md)
   - [Actions](actions.md)
-- [Data Flow](data-flow.md)
+  - [Modules](modules.md)
 - [Application Structure](structure.md)
 - [Plugins](plugins.md)
 - [Strict Mode](strict.md)

+ 0 - 89
docs/en/data-flow.md

@@ -1,89 +0,0 @@
-# Data Flow
-
-Let's build a simple counter app with Vuex to get a better understanding of the data flow inside Vuex apps. Note this is a trivial example solely for the purpose of explaining the concepts - in practice you don't need Vuex for such simple tasks.
-
-### The Store
-
-``` js
-// store.js
-import Vue from 'vue'
-import Vuex from 'vuex'
-
-Vue.use(Vuex)
-
-// app initial state
-const state = {
-  count: 0
-}
-
-// define possible mutations
-const mutations = {
-  INCREMENT (state) {
-    state.count++
-  },
-  DECREMENT (state) {
-    state.count--
-  }
-}
-
-// create the store
-export default new Vuex.Store({
-  state,
-  mutations
-})
-```
-
-### Actions
-
-``` js
-// actions.js
-export const increment = ({ dispatch }) => dispatch('INCREMENT')
-export const decrement = ({ dispatch }) => dispatch('DECREMENT')
-```
-
-### Use It with Vue
-
-**Template**
-
-``` html
-<div id="app">
-  Clicked: {{ count }} times
-  <button v-on:click="increment">+</button>
-  <button v-on:click="decrement">-</button>
-</div>
-```
-
-**Script**
-
-``` js
-// We are importing and injecting the store here because
-// this is the root. In larger apps you only do this once.
-import store from './store'
-import { increment, decrement } from './actions'
-
-const app = new Vue({
-  el: '#app',
-  store,
-  vuex: {
-    getters: {
-      count: state => state.count
-    },
-    actions: {
-      increment,
-      decrement
-    }
-  }
-})
-```
-
-Here you will notice the component itself is extremely simple: it simply displays some state from the Vuex store (not even owning its own data), and calls some store actions on user input events.
-
-You will also notice the data flow is unidirectional, as it should be in Flux:
-
-1. User input in the component triggers action calls;
-2. Actions dispatch mutations that change the state;
-3. Changes in state flow from the store back into the component via getters.
-
-<p align="center">
-  <img width="700px" src="vuex.png">
-</p>

+ 77 - 0
docs/en/getters.md

@@ -0,0 +1,77 @@
+
+# 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
+computed: {
+  doneTodosCount () {
+    return this.$store.state.todos.filter(todo => todo.done).length
+  }
+}
+```
+
+If more than one component needs to make use of this, we have to either duplicate the function, or extract it into a shared helper and import it in multiple places - both are less than ideal.
+
+Vuex allows us to define "getters" in the store (think of them as computed properties for stores):
+
+``` js
+const store = new Vuex.Store({
+  state: {
+    todos: [
+      { id: 1, text: '...', done: true },
+      { id: 2, text: '...', done: false }
+    ]
+  },
+  getters: {
+    doneTodosCount: state => {
+      return state.todos.filter(todo => todo.done).length
+    }
+  }
+})
+```
+
+The getters will be exposed on the `store.getters` object:
+
+``` js
+store.getters.doneTodosCount // -> 1
+```
+
+We can now easily make use of it inside any component:
+
+``` js
+computed: {
+  doneTodosCount () {
+    return this.$store.getters.doneTodosCount
+  }
+}
+```
+
+### The `mapGetters` Helper
+
+The `mapGetters` helper simply maps store getters to local computed properties:
+
+``` js
+import { mapState } from 'vuex'
+
+export default {
+  // ...
+  computed: {
+    // mix the getters into computed with object spread operator
+    ...mapGetters([
+      'doneTodosCount',
+      'anotherGetter',
+      // ...
+    ])
+  }
+}
+```
+
+If you want to map a getter to a different name, use an object:
+
+``` js
+mapGetters({
+  // map this.doneCount to store.getters.doneTodosCount
+  doneCount: 'doneTodosCount'
+})
+```

+ 17 - 30
docs/en/getting-started.md

@@ -4,50 +4,37 @@ At the center of every Vuex application is the **store**. A "store" is basically
 
 1. Vuex stores are reactive. When Vue components retrieve state from it, they will reactively and efficiently update if the store's state changes.
 
-2. You cannot directly mutate the store's state. The only way to change a store's state is by explicitly dispatching **mutations**. This makes every state change easily track-able, and enables tooling that helps us better understand our applications.
+2. You cannot directly mutate the store's state. The only way to change a store's state is by explicitly **committing mutations**. This ensures every state change leaves a track-able record, and enables tooling that helps us better understand our applications.
 
 ### The Simplest Store
 
-> **NOTE:** We will be using ES2015 syntax for code examples for the rest of the docs. If you haven't picked it up, [you should](https://babeljs.io/docs/learn-es2015/)! The doc also assumes you are already familiar with the concepts discussed in [Building Large-Scale Apps with Vue.js](http://vuejs.org/guide/application.html).
+> **NOTE:** We will be using ES2015 syntax for code examples for the rest of the docs. If you haven't picked it up, [you should](https://babeljs.io/docs/learn-es2015/)!
 
-Creating a Vuex store is pretty straightforward - just provide an initial state object, and some mutations:
+After [installing](installation.md) Vuex, let's create a store. It is pretty straightforward - just provide an initial state object, and some mutations:
 
 ``` js
-import Vuex from 'vuex'
-
-const state = {
-  count: 0
-}
-
-const mutations = {
-  INCREMENT (state) {
-    state.count++
+// Make sure to call Vue.use(Vuex) first if using a module system
+
+const store = new Vuex.Store({
+  state: {
+    count: 0
+  },
+  mutations: {
+    INCREMENT (state) {
+      state.count++
+    }
   }
-}
-
-export default new Vuex.Store({
-  state,
-  mutations
 })
 ```
 
-Now, you can access the state object as `store.state`, and trigger a mutation by dispatching its name:
+Now, you can access the state object as `store.state`, and trigger a state change with the `store.commit` method:
 
 ``` js
-store.dispatch('INCREMENT')
+store.commit('INCREMENT')
 
 console.log(store.state.count) // -> 1
 ```
 
-If you prefer object-style dispatching, you can also do this:
-
-``` js
-// same effect as above
-store.dispatch({
-  type: 'INCREMENT'
-})
-```
-
-Again, the reason we are dispatching a mutation instead of changing `store.state.count` directly, is because we want to explicitly track it. This simple convention makes your intention more explicit, so that you can reason about state changes in your app better when reading the code. In addition, this gives us the opportunity to implement tools that can log every mutation, take state snapshots, or even perform time travel debugging.
+Again, the reason we are committing a mutation instead of changing `store.state.count` directly, is because we want to explicitly track it. This simple convention makes your intention more explicit, so that you can reason about state changes in your app better when reading the code. In addition, this gives us the opportunity to implement tools that can log every mutation, take state snapshots, or even perform time travel debugging.
 
-Now this is just the simplest possible example of what a store is. But Vuex is more than just the store. Next, we will discuss some core concepts in depth: [State](state.md), [Mutations](mutations.md) and [Actions](actions.md).
+Next, let's see [how to use the State inside Vue components](state.md).

+ 0 - 0
docs/en/modules.md


+ 0 - 2
docs/en/mutations.md

@@ -3,8 +3,6 @@
 Vuex mutations are essentially events: each mutation has a **name** and a **handler**. The handler function will receive the state as the first argument:
 
 ``` js
-import Vuex from 'vuex'
-
 const store = new Vuex.Store({
   state: {
     count: 1

+ 54 - 113
docs/en/state.md

@@ -1,4 +1,4 @@
-# State and Getters
+# State
 
 ### Single State Tree
 
@@ -11,146 +11,87 @@ The single state tree does not conflict with modularity - in later chapters we w
 So how do we display state inside the store in our Vue components? Since Vuex stores are reactive, the simplest way to "retrieve" state from it is simply returning some store state from within a [computed property](http://vuejs.org/guide/computed.html):
 
 ``` js
-// in a Vue component definition
-computed: {
-  count: function () {
-    return store.state.count
+// let's create a Counter component
+const Counter = {
+  template: `<div>{{ count }}</div>`,
+  computed: {
+    count () {
+      return store.state.count
+    }
   }
 }
 ```
 
 Whenever `store.state.count` changes, it will cause the computed property to re-evaluate, and trigger associated DOM updates.
 
-However, this pattern causes the component to rely on the global store singleton. This makes it harder to test the component, and also makes it difficult to run multiple instances of the app using the same set of components. In large applications, we may want to "inject" the store into child components from the root component. Here's how to do it:
-
-1. Install Vuex and connect your root component to the store:
-
-  ``` js
-  import Vue from 'vue'
-  import Vuex from 'vuex'
-  import store from './store'
-  import MyComponent from './MyComponent'
-
-  // important, teaches Vue components how to
-  // handle Vuex-related options
-  Vue.use(Vuex)
-
-  var app = new Vue({
-    el: '#app',
-    // provide the store using the "store" option.
-    // this will inject the store instance to all child components.
-    store,
-    components: {
-      MyComponent
-    }
-  })
-  ```
-
-  By providing the `store` option to the root instance, the store will be injected into all child components of the root and will be available on them as `this.$store`. However it's quite rare that we will need to actually reference it.
-
-2. Inside child components, retrieve state with **getter** functions in the `vuex.getters` option:
-
-  ``` js
-  // MyComponent.js
-  export default {
-    template: '...',
-    data () { ... },
-    // this is where we retrieve state from the store
-    vuex: {
-      getters: {
-        // a state getter function, which will
-        // bind `store.state.count` on the component as `this.count`
-        count: function (state) {
-          return state.count
-        }
-      }
-    }
-  }
-  ```
-
-  Note the special `vuex` option block. This is where we specify what state the component will be using from the store. For each property name, we specify a getter function which receives the entire state tree as the only argument, and then selects and returns a part of the state, or a computed value derived from the state. The returned result will be set on the component using the property name, just like a computed property.
-
-  In a lot of cases, the "getter" function can be very succinct using ES2015 arrow functions:
+However, this pattern causes the component to rely on the global store singleton. When using a module system, it requires importing the store in every component that uses store state, and also requires mocking when testing the component.
 
-  ``` js
-  vuex: {
-    getters: {
-      count: state => state.count
-    }
-  }
-  ```
-
-### Getters Must Be Pure
-
-All Vuex getters must be [pure functions](https://en.wikipedia.org/wiki/Pure_function) - they take the entire state tree in, and return some value solely based on that state. This makes them more testable, composable and efficient. It also means **you cannot rely on `this` inside getters**.
-
-If you do need access to `this`, for example to compute derived state based on the component's local state or props, you need to define separate, plain computed properties:
+Vuex provides a mechanism to "inject" the store into all child components from the root component with the `store` option (enabled by `Vue.use(Vuex)`):
 
 ``` js
-vuex: {
-  getters: {
-    currentId: state => state.currentId
-  }
-},
-computed: {
-  isCurrent () {
-    return this.id === this.currentId
-  }
-}
+const app = new Vue({
+  el: '#app',
+  // provide the store using the "store" option.
+  // this will inject the store instance to all child components.
+  store,
+  components: { Counter },
+  template: `
+    <div class="app">
+      <counter></counter>
+    </div>
+  `
+})
 ```
 
-### Getters Can Return Derived State
-
-Vuex state getters are computed properties under the hood, this means you can leverage them to reactively (and efficiently) compute derived state. For example, say in the state we have an array of `messages` containing all messages, and a `currentThreadID` representing a thread that is currently being viewed by the user. What we want to display to the user is a filtered list of messages that belongs to the current thread:
+By providing the `store` option to the root instance, the store will be injected into all child components of the root and will be available on them as `this.$store`. Let's update our `Counter` implementation:
 
 ``` js
-vuex: {
-  getters: {
-    filteredMessages: state => {
-      return state.messages.filter(message => {
-        return message.threadID === state.currentThreadID
-      })
+const Counter = {
+  template: `<div>{{ count }}</div>`,
+  computed: {
+    count () {
+      return this.$store.state.count
     }
   }
 }
 ```
 
-Because Vue.js computed properties are automatically cached and only re-evaluated when a reactive dependency changes, you don't need to worry about this function being called on every mutation.
-
-### Sharing Getters Across Multiple Components
+### The `mapState` Helper
 
-As you can see, the `filteredMessages` getter may be useful inside multiple components. In that case, it's a good idea to share the same function between them:
-
-``` js
-// getters.js
-export function filteredMessages (state) {
-  return state.messages.filter(message => {
-    return message.threadID === state.currentThreadID
-  })
-}
-```
+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 and help us save some keystrokes:
 
 ``` js
-// in a component...
-import { filteredMessages } from './getters'
+// in standalone builds helpers are exposed as Vuex.mapState
+import { mapState } from 'vuex'
 
 export default {
-  vuex: {
-    getters: {
-      filteredMessages
+  // ...
+  computed: mapState({
+    // arrow functions can make the code very succinct!
+    count: state => state.count,
+
+    // to access local state with `this`, a normal function must be used
+    countPlusLocalState (state) {
+      return state.count + this.localCount
     }
-  }
+  })
 }
 ```
 
-Because getters are pure, getters shared across multiple components are efficiently cached: when dependencies change, they only re-evaluate once for all components that use them.
+### Object Spread Operator
 
-> Flux reference: Vuex getters can be roughly compared to [`mapStateToProps`](https://github.com/rackt/react-redux/blob/master/docs/api.md#connectmapstatetoprops-mapdispatchtoprops-mergeprops-options) in Redux. However, because they leverage Vue's computed properties memoization under the hood, they are more efficient than `mapStateToProps`, and more similar to [reselect](https://github.com/reactjs/reselect).
+Note that `mapState` returns an object. How do we use it in combination with other local computed properties? Normally, we'd have to use a utility to merge multiple objects into one so that we can pass the final object to `computed`. However with the [object spread operator](https://github.com/sebmarkbage/ecmascript-rest-spread) (which is a stage-2 ECMASCript proposal), we can greatly simplify the syntax:
 
-### Components Are Not Allowed to Directly Mutate State
-
-It's important to remember that **components should never directly mutate Vuex store state**. Because we want every state mutation to be explicit and trackable, all vuex store state mutations must be conducted inside the store's mutation handlers.
+``` js
+computed: {
+  localComputed () { /* ... */ },
+  // mix this into the outer object with the object spread operator
+  ...mapState({
+    // ...
+  })
+}
+```
 
-To help enforce this rule, when in [Strict Mode](strict.md), if a store's state is mutated outside of its mutation handlers, Vuex will throw an error.
+### Components Can Still Have Local State
 
-With this rule in place, our Vue components now hold a lot less responsibility: they are bound to Vuex store state via read-only getters, and the only way for them to affect the state is by somehow triggering **mutations** (which we will discuss later). They can still possess and operate on their local state if necessary, but we no longer put any data-fetching or global-state-mutating logic inside individual components. They are now centralized and handled inside Vuex related files, which makes large applications easier to understand and maintain.
+Using Vuex doesn't mean you should put **all** the state in Vuex. Although putting more state into Vuex makes your state mutations more explicit and debuggable, sometimes it could also make the code more verbose and indirect. If a piece of state strictly belongs to a single component, it could be just fine leaving it as local state. You should weigh the trade-offs and make decisions that fit the development needs of your app.

+ 8 - 0
docs/old/README.md

@@ -0,0 +1,8 @@
+# Vuex 1.0 Docs
+
+- [English](https://github.com/vuejs/vuex/tree/1.0/docs/en)
+- [Chinese](https://github.com/vuejs/vuex/tree/1.0/docs/zh-cn)
+- [Japanese](https://github.com/vuejs/vuex/tree/1.0/docs/ja)
+- [Spanish](https://github.com/vuejs/vuex/tree/1.0/docs/es)
+- [Portuguese](https://github.com/vuejs/vuex/tree/1.0/docs/pt)
+- [Italian](https://github.com/vuejs/vuex/tree/1.0/docs/it)

+ 0 - 0
docs/old/SUMMARY.md