浏览代码

add spanish docs translation (#164)

Miljan 9 年之前
父节点
当前提交
5379b0c9f7

+ 1 - 0
docs/es/README.md

@@ -0,0 +1 @@
+SUMMARY.md

+ 19 - 0
docs/es/SUMMARY.md

@@ -0,0 +1,19 @@
+# Tabla de contenidos
+
+> Asegúrate de leer estas secciones en orden.
+
+- [Qué es Vuex?](intro.md)
+- [Empezando](getting-started.md)
+- [Tutorial](tutorial.md)
+- Conceptos Básicos
+  - [Estado y Obtenedores](state.md)
+  - [Mutaciones](mutations.md)
+  - [Acciones](actions.md)
+- [Flujo de datos](data-flow.md)
+- [Estructura de la Aplicación](structure.md)
+- [Middlewares](middlewares.md)
+- [Modo estricto](strict.md)
+- [Manejo de formularios](forms.md)
+- [Probando](testing.md)
+- [Recarga en caliente](hot-reload.md)
+- [Referencia API](api.md)

+ 134 - 0
docs/es/actions.md

@@ -0,0 +1,134 @@
+# Acciones
+
+> Acciones en Vuex son de hecho "creadores de acción" en las definiciones de vanilla flux, pero encuentro ese término más confuso que útil.
+
+Acciones son simplemente funciones que despachan mutaciones. Por convenio, las acciones de Vuex siempre esperan una instancia del almacén como su primer argumento, seguido por argumentos adicionales opcionales.
+
+``` js
+// la acción más simple
+function increment (store) {
+  store.dispatch('INCREMENT')
+}
+
+// acción con argumentos adicionales
+// usando la destructuración de argumentos del ES2015
+function incrementBy ({ dispatch }, amount) {
+  dispatch('INCREMENT', amount)
+}
+```
+
+Esto puede parecer tonto a primera vista: ¿Por qué no despachamos las mutaciones directamente? Bien, recuerda que **las mutaciones deben ser síncronas**. Las acciones no. Podemos realizar operaciones **asíncronas** dentro de una acción:
+
+``` js
+function incrementAsync ({ dispatch }) {
+  setTimeout(() => {
+    dispatch('INCREMENT')
+  }, 1000)
+}
+```
+
+Un ejemplo más práctico sería una acción para procesar un carrito de la compra, lo cual involucra **llamar a una API asíncrona** y **despachar múltiples mutaciones**:
+
+``` js
+function checkout ({ dispatch, state }, products) {
+  // guarda los actuales artículos del carrito
+  const savedCartItems = [...state.cart.added]
+  // envía la solicitud y con optimismo vacía el carrito
+  dispatch(types.CHECKOUT_REQUEST)
+  // el API de la tienda acepta una retrollamada en caso de éxito
+  // y otra en caso de fallo
+  shop.buyProducts(
+    products,
+    // éxito
+    () => dispatch(types.CHECKOUT_SUCCESS),
+    // fallo
+    () => dispatch(types.CHECKOUT_FAILURE, savedCartItems)
+  )
+}
+```
+
+Ten en cuenta que en vez de esperar valores de retorno o pasar retrollamadas a acciones, el resultado de llamar al API asíncrono es también gestionado despachando mutaciones. La regla de oro es que **los únicos efectos secundarios producidos por llamar acciones deberían ser mutaciones despachadas**.
+
+### Llamando acciones en componentes
+
+Puedes haber notado que las funciones asociadas a las acciones no son directamente ejecutables sin la referencia a una instancia del almacén. Técnicamente, podemos invocar una acción llamando `action(this.$store)` dentro de un método, pero es mejor si directamente podemos asignar las acciones como métodos de los componentes para así poder fácilmente referenciarlos dentro de las plantillas. Podemos hacerlo usando la opción `vuex.actions`:
+
+``` js
+// dentro del componente
+import { incrementBy } from './actions'
+
+const vm = new Vue({
+  vuex: {
+    getters: { ... }, // getters del estado
+    actions: {
+      incrementBy // abreviación de un objeto literal en ES6, asignación usando el mismo nombre
+    }
+  }
+})
+```
+
+Lo que el código anterior hace es asignar la acción pura `incrementBy` a la instancia del almacén del componente, y exponerlo en el componente como un método de instancia, `vm.incrementBy`. Cualquier argumento pasado a `vm.incrementBy` será pasado a la función de la acción después del primer argumento que es el almacén, así pues:
+
+``` js
+vm.incrementBy(1)
+```
+
+es equivalente a:
+
+``` js
+incrementBy(vm.$store, 1)
+```
+
+Pero la ventaja es que se puede asignar más fácilmente dentro de la plantilla del componente:
+
+``` html
+<button v-on:click="incrementBy(1)">incrementar por uno</button>
+```
+
+Puedes obviamente usar un nombre de método diferente cuando asignes las acciones:
+
+``` js
+// dentro del componente
+import { incrementBy } from './actions'
+
+const vm = new Vue({
+  vuex: {
+    getters: { ... },
+    actions: {
+      plus: incrementBy // asignar usando un nombre diferente
+    }
+  }
+})
+```
+
+Ahora la acción será asignada como `vm.plus` en vez de `vm.incrementBy`.
+
+### Acciones en línea
+
+Si la acción es específica del componente, puedes usar un atajo y definirla en línea:
+
+``` js
+const vm = new Vue({
+  vuex: {
+    getters: { ... },
+    actions: {
+      plus: ({ dispatch }) => dispatch('INCREMENT')
+    }
+  }
+})
+```
+
+### Asignando todas las acciones
+
+Si simplemente quieres asignar todas las acciones compartidas:
+
+``` js
+import * as actions from './actions'
+
+const vm = new Vue({
+  vuex: {
+    getters: { ... },
+    actions // asignar todas las acciones
+  }
+})
+```

+ 107 - 0
docs/es/api.md

@@ -0,0 +1,107 @@
+# Referencia API
+
+### Vuex.Store
+
+``` js
+import Vuex from 'vuex'
+
+const store = new Vuex.Store({ ...options })
+```
+
+### Opciones de construcción de Vuex.Store
+
+- **state**
+
+  - tipo: `Object`
+
+    El objeto de estado raíz para el almacén Vuex.
+
+    [Detalles](state.md)
+
+- **mutations**
+
+  - tipo: `Object`
+
+    Un objeto en el que cada clave de entrada es el nombre de la mutación y el valor es una función de controlador de mutación. La función de controlador recibe siempre `state` como primer argumento, y seguido recibe todos los argumentos que se pasan a la llamada de despacho.
+
+    [Detalles](mutations.md)
+
+- **modules**
+
+  - tipo: `Object`
+
+    Un objeto que contiene submódulos a combinar en el almacén, en la forma de:
+
+    ``` js
+    {
+      key: {
+        state,
+        mutations
+      },
+      ...
+    }
+    ```
+
+    Cada módulo puede contener `state` y `mutations` similares a las opciones raíz. El estado del módulo se une al estado raíz del almacén usando las claves del módulo. Las mutaciones de un módulo sólo reciben el estado propio del módulo como primer argumento en lugar del estado raíz.
+
+- **middlewares**
+
+  - tipo: `Array<Object>`
+
+    Un conjunto de objetos de middleware que se encuentran en la forma de:
+
+    ``` js
+    {
+      snapshot: Boolean, // por defecto: false
+      onInit: Function,
+      onMutation: Function
+    }
+    ```
+
+    Todos los campos son opcionales. [Detalles](middlewares.md)
+
+- **strict**
+
+  - tipo: `Boolean`
+  - por defecto: `false`
+
+    Fuerza el almacén Vuex a modo estricto. En modo estricto cualquier mutación al estado de Vuex fuera de los manipuladores de mutación generará un error.
+
+    [Detalles](strict.md)
+
+### Propiedades de instancia del Vuex.Store
+
+- **state**
+
+  - tipo: `Object`
+
+    El estado raíz. De sólo lectura.
+
+### Métodos de instancia de Vuex.Store
+
+- **dispatch(mutationName: String, ...args) | dispatch(mutation: Object)**
+
+  Directamente despachar una mutación. Esto es útil en ciertas situaciones, pero en general deberías preferir el uso de acciones en el código de la aplicación.
+
+  *Object-Style Dispatch*
+
+  > requiere >=0.6.2
+
+  También puedes despachar mutaciones utilizando objetos:
+
+  ``` js
+  store.dispatch({
+    type: 'INCREMENT',
+    payload: 10
+  })
+  ```
+
+- **watch(pathOrGetter: String|Function, cb: Function, [options: Object])**
+
+  Observa una ruta o el valor de una función obtenedor, y llamar a la retrollamada cuando el valor cambia. Acepta un objeto opcional de opciones que tiene las mismas opciones como el método `vm.$watch` de Vue.
+
+  Para dejar de observar, llamar a la función de manipulación devuelto.
+
+- **hotUpdate(newOptions: Object)**
+
+  Intercambio en caliente de nuevas acciones y mutaciones. [Detalles](hot-reload.md)

+ 1 - 0
docs/es/book.json

@@ -0,0 +1 @@
+../book.json

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

@@ -0,0 +1,89 @@
+# Flujo de datos
+
+Construyamos una app contador simple con Vuex para obtener una mejor comprensión del flujo de datos dentro de aplicaciones Vuex. Ten en cuenta que este es un ejemplo trivial con el único fin de explicar los conceptos - en la práctica no necesitas Vuex para tareas tan sencillas.
+
+### El almacén
+
+``` js
+// store.js
+import Vue from 'vue'
+import Vuex from 'vuex'
+
+Vue.use(Vuex)
+
+// estado inicial del app
+const state = {
+  count: 0
+}
+
+// define posibles mutaciones
+const mutations = {
+  INCREMENT (state) {
+    state.count++
+  },
+  DECREMENT (state) {
+    state.count--
+  }
+}
+
+// crea el almacén
+export default new Vuex.Store({
+  state,
+  mutations
+})
+```
+
+### Acciones
+
+``` js
+// actions.js
+export const increment = ({ dispatch }) => dispatch('INCREMENT')
+export const decrement = ({ dispatch }) => dispatch('DECREMENT')
+```
+
+### Usalo con Vue
+
+**Plantilla**
+
+``` html
+<div id="app">
+  Tocado: {{ count }} veces
+  <button v-on:click="increment">+</button>
+  <button v-on:click="decrement">-</button>
+</div>
+```
+
+**Script**
+
+``` js
+// Estamos importando e inyectando el almacén aquí porque
+// esta es la raíz. En aplicaciones más grandes esto lo haces sólo una vez.
+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
+    }
+  }
+})
+```
+
+Aquí te darás cuenta que el componente en sí es muy sencillo: simplemente muestra un estado del almacén Vuex (ni siquiera tiene datos propios), y llama a algunas acciones de almacén basado en eventos de entrada de usuario.
+
+También te darás cuenta que el flujo de datos es unidireccional, como debería ser en Flux:
+
+1. Entrada de usuario en el componente desencadena llamadas de acción;
+2. Acciones despachan mutaciones que cambian el estado;
+3. Cambios en el flujo de estado desde el almacén de vuelta al componente mediante obtenedores.
+
+<p align="center">
+  <img width="700px" src="vuex.png">
+</p>

+ 41 - 0
docs/es/forms.md

@@ -0,0 +1,41 @@
+# Manejo de formularios
+
+Al utilizar Vuex en modo estricto, podría ser un poco difícil usar `v-model` en una parte de estado que pertenece a Vuex:
+
+``` html
+<input v-model="obj.message">
+```
+
+Asumiendo `obj` es una propiedad computarizada que devuelve un Objeto del almacén, aquí el `v-model` intentará mutar directamente `obj.message` cuando el usuario escriba en la entrada de texto. En modo estricto, esto dará lugar a un error debido a que la mutación no se lleva a cabo dentro de un controlador de mutación Vuex explícito.
+
+La "manera de Vuex" es registrar el valor de `<input>` y llamar a una acción en el evento `input` o `change`:
+
+``` html
+<input :value="message" @input="updateMessage">
+```
+``` js
+// ...
+vuex: {
+  getters: {
+    message: state => state.obj.message
+  },
+  actions: {
+    updateMessage: ({ dispatch }, e) => {
+      dispatch('UPDATE_MESSAGE', e.target.value)
+    }
+  }
+}
+```
+
+Y aquí está el controlador de mutación:
+
+``` js
+// ...
+mutations: {
+  UPDATE_MESSAGE (state, message) {
+    state.obj.message = message
+  }
+}
+```
+
+Es cierto que esto es un poco más verboso que un simple `v-model`, pero tal es el coste de hacer los cambios de estado explícitos y registrables. Al mismo tiempo, ten en cuenta que Vuex no exige poner todo el estado dentro de un almacén Vuex - si no deseas realizar un seguimiento de las mutaciones por las interacciones de formulario en absoluto, sólo tienes que mantener el estado del formulario fuera de Vuex como estado local del componente, lo que te permite aprovechar libremente `v-model`.

+ 53 - 0
docs/es/getting-started.md

@@ -0,0 +1,53 @@
+# Empezando
+
+En el centro de toda aplicación Vuex está el **almacén**. Un almacén o "store" es básicamente un contenedor que guarda el **estado** de tu aplicación. Hay dos hechos que hacen al almacén Vuex diferente a un objeto global plano:
+
+1. Los almacenes Vuex son reactivos. Cuando los Vue componentes recuperan un estado, el mismo reactiva y eficientemente será actualizado si el estado del almacén cambia.
+
+2. No puedes directamente mutar el estado del almacén. La única manera de cambiar el estado del almacén es despachando explícitamente **mutaciones**. Esto hace cada cambio de estado fácilmente rastreable, y habilita utilidades que nos ayudan a comprender mejor nuestras aplicaciones.
+
+### El almacén más simple
+
+> **NOTA:** Usaremos la sintaxis del ES2015 para los ejemplos de código para el resto de la documentación. Si aún no lo estás usando, [deberías](https://babeljs.io/docs/learn-es2015/)! La documentación además asume que ya estás familiarizado con los conceptos discutidos en [Construyendo Apps de gran envergadura con Vue.js](http://vuejs.org/guide/application.html).
+
+La creación de un almacén Vuex es bastante sencillo - simplemente proporciona un objeto con el estado inicial, y algunas mutaciones:
+
+``` js
+import Vuex from 'vuex'
+
+const state = {
+  count: 0
+}
+
+const mutations = {
+  INCREMENT (state) {
+    state.count++
+  }
+}
+
+export default new Vuex.Store({
+  state,
+  mutations
+})
+```
+
+Ahora, puedes acceder el objeto del estado como `store.state`, y ejecutar una mutación despachando su nombre:
+
+``` js
+store.dispatch('INCREMENT')
+
+console.log(store.state.count) // -> 1
+```
+
+Si prefieres despachar con el estilo de objetos, también puedes hacer lo siguiente:
+
+``` js
+// mismo efecto al anterior
+store.dispatch({
+  type: 'INCREMENT'
+})
+```
+
+De nuevo, la razón por la que estamos despachando una mutación en vez cambiar `store.state.count` directamente, es porque queremos explícitamente rastrearlo. Esta simple convención hace tu intención más explícita, para que así puedas razonar mejor sobre cambios de estado en tu app cuando vayas leyendo el código. Adicionalmente, eso nos da la oportunidad de implementar utilidades que puedan registrar cada mutación, tomar instantáneas de estado, o incluso realizar depuraciones con viaje en el tiempo.
+
+Ahora, esto es tan sólo el ejemplo más simple posible de lo que es el almacén. Pero Vuex es más que solamente el almacén. Seguidamente, discutiremos algunos conceptos básicos en profundidad: [Estado](state.md), [Mutaciones](mutations.md) y [Acciones](actions.md).

+ 44 - 0
docs/es/hot-reload.md

@@ -0,0 +1,44 @@
+# Recarga en caliente
+
+Vuex soporta recarga de mutaciones en caliente, módulos, acciones y obtenedores durante el desarrollo, utilizando [Hot Module Replacement API](https://webpack.github.io/docs/hot-module-replacement.html) de Webpack. También puedes utilizarlo en Browserify con el plugin [browserify-hmr](https://github.com/AgentME/browserify-hmr/).
+
+Para las mutaciones y los módulos, es necesario utilizar el método `store.hotUpdate()` del API:
+
+``` js
+// store.js
+import Vue from 'vue'
+import Vuex from 'vuex'
+import mutations from './mutations'
+import moduleA from './modules/a'
+
+Vue.use(Vuex)
+
+const state = { ... }
+
+const store = new Vuex.Store({
+  state,
+  mutations,
+  modules: {
+    a: moduleA
+  }
+})
+
+if (module.hot) {
+  // aceptar acciones y mutaciones como módulos en caliente
+  module.hot.accept(['./mutations', './modules/a'], () => {
+    // requieren los módulos actualizados
+    // hay que añadir .default aquí debido a la producción del módulo de babel 6
+    const newMutations = require('./mutations').default
+    const newModuleA = require('./modules/a').default
+    // intercambio de las nuevas acciones y mutaciones
+    store.hotUpdate({
+      mutations: newMutations,
+      modules: {
+        a: newModuleA
+      }
+    })
+  })
+}
+```
+
+No tienes que hacer nada específico para acciones y obtenedores. El sistema de reemplazo de módulo en caliente de Webpack "empujará" los cambios hasta la cadena de dependencias - y los cambios en las acciones y obtenedores subirán a los componentes Vue que los importaron. Dado que los componentes Vue cargados a través de `vue-loader` son recargables en caliente por defecto, estos componentes afectados se recargarán en caliente a sí mismos y usarán las acciones y obtenedores actualizados.

+ 13 - 0
docs/es/intro.md

@@ -0,0 +1,13 @@
+## Qué es Vuex?
+
+Vuex es una arquitectura para el desarrollo de aplicaciones en Vue.js con manejo de estado centralizado. Está inspirado en [Flux](https://facebook.github.io/flux/) y [Redux](https://github.com/rackt/redux), pero con conceptos simplificados e implementación diseñada específicamente para tomar ventaja del sistema reactivo de Vue.js.
+
+## Por qué lo necesito?
+
+Si tu app es simple, quizás no necesites Vuex. No lo apliques prematuramente. Pero si estás construyendo un SPA de medio-grandes dimensiones, probablemente te hayas encontrado en situaciones que te han hecho pensar en cómo mejor estructuras las cosas fuera de tu componente Vue. Aquí es donde Vuex entra en juego.
+
+Cuando usamos Vue.js a solas, a menudo tendemos a almacenar el estado "dentro" de nuestros componentes. Lo que significa, cada componente guarda una pieza del estado de nuestra aplicación, y como resultado el estado es dispersado por todos lados. Sin embargo, a veces una parte del estado necesita ser compartido por múltiples componentes. Una práctica común es dejar que un componente "envíe" algún estado a otros componentes usando el sistema de eventos personalizado. El problema con este patrón es que el flujo de eventos dentro de grandes ramas de componentes puede volverse complejo rápidamente, y a menudo es difícil encontrar la causa cuando algo va mal.
+
+Para tratar mejor estados compartidos en grandes aplicaciones, necesitamos diferenciar entre **estado local del componente** y **estado a nivel de aplicación**. El estado de aplicación no pertenece a un componente específico, pero nuestros componentes pueden observarlo para actualizaciones de DOM reactivos. Centralizando su manejo en un único sitio, no necesitamos ir pasando eventos, porque todo lo que afecta a más de un componente debería pertenecer allí. En adición esto nos permite grabar e inspeccionar cada mutación para un entendimiento más fácil de los cambios de estado, e incluso poner en práctica cosas avanzadas como la depuración con viaje en el tiempo.
+
+Vuex también pone en vigor algunas opiniones sobre cómo dividir la lógica de la administración del estado en diferentes lugares, pero aun así permite suficiente flexibilidad para la estructura del código actual.

+ 83 - 0
docs/es/middlewares.md

@@ -0,0 +1,83 @@
+# Middlewares
+
+Almacenes Vuex aceptan la opción `middlewares` que expone ganchos para cada mutación (Ten en cuenta que esto no tiene ninguna relación con Redux middlewares). Vuex middleware es simplemente un objeto que implementa algunas funciones de gancho:
+
+``` js
+const myMiddleware = {
+  onInit (state, store) {
+    // registar estado inicial
+  },
+  onMutation (mutation, state, store) {
+    // llamado después de cada mutación.
+    // La mutación viene en formato { type, payload }
+  }
+}
+```
+
+Y puede ser utilizado de esta manera:
+
+``` js
+const store = new Vuex.Store({
+  // ...
+  middlewares: [myMiddleware]
+})
+```
+
+Por defecto, un middleware recibe el objeto `state` real. Un middleware también puede recibir el `store` en sí con el fin de despachar mutaciones. Ya que los middlewares se utilizan principalmente para fines de depuración o la persistencia de datos, a los mismos **no se les permite mutar el estado**.
+
+A veces, un middleware puede querer recibir "instantáneas" del estado, y también comparar el estado post-mutación con el estado pre-mutación. Tal middlewares deben declarar la opción `snapshot: true`:
+
+``` js
+const myMiddlewareWithSnapshot = {
+  snapshot: true,
+  onMutation (mutation, nextState, prevState, store) {
+    // nextState y prevState son instantáneas de profunda clonación
+    // del estado antes y después de la mutación.
+  }
+}
+```
+
+**Middlewares que toman instantáneas del estado deben utilizarse sólo durante el desarrollo.** Usando Webpack o Browserify, podemos dejar que nuestras herramientas de compilación lo manejen por nosotros:
+
+``` js
+const store = new Vuex.Store({
+  // ...
+  middlewares: process.env.NODE_ENV !== 'production'
+    ? [myMiddlewareWithSnapshot]
+    : []
+})
+```
+
+El middleware será utilizado por defecto. Para la producción, utilice la configuración de compilación descrita [aquí](http://vuejs.org/guide/application.html#Deploying-for-Production) para convertir el valor de `process.env.NODE_ENV! == 'Production'` a `false` para la versión final.
+
+### Middleware registrador incorporado
+
+Vuex viene con un middleware registrador para la depuración común:
+
+``` js
+import createLogger from 'vuex/logger'
+
+const store = new Vuex.Store({
+  middlewares: [createLogger()]
+})
+```
+
+La función `createLogger` toma algunas opciones:
+
+``` js
+const logger = createLogger({
+  collapsed: false, // auto expande mutaciones registradas
+  transformer (state) {
+    // transforma el estado antes de registrarlo.
+    // por ejemplo devuelve sólo un sub-árbol específico
+    return state.subTree
+  },
+  mutationTransformer (mutation) {
+    // las mutaciones se registran en el formato de { type, payload }
+    // podemos formatearlo en el modo que queramos.
+    return mutation.type
+  }
+})
+```
+
+Ten en cuenta que el middleware registrador toma instantáneas del estado, así que utilizalo sólo durante el desarrollo.

+ 164 - 0
docs/es/mutations.md

@@ -0,0 +1,164 @@
+# Mutaciones
+
+Las mutaciones Vuex son esencialmente eventos: cada mutación tiene un **nombre** y un **manejador**. La función del manejador recibirá el estado como el primer argumento:
+
+``` js
+import Vuex from 'vuex'
+
+const store = new Vuex.Store({
+  state: {
+    count: 1
+  },
+  mutations: {
+    INCREMENT (state) {
+      // mutar estado
+      state.count++
+    }
+  }
+})
+```
+
+El uso de mayúsculas para los nombres de mutación es sólo una convención para que sea más fácil diferenciarlos de las funciones planas.
+
+No puedes llamar directamente a un manejador de mutación. Las opciones aquí son más bien un registro de eventos: "Cuando un evento `INCREMENT` es despachado, llama a este manejador." Para invocar un manejador de mutación, es necesario despachar un evento de mutación:
+
+``` js
+store.dispatch('INCREMENT')
+```
+
+### Despachar con argumentos
+
+También es posible pasar argumentos:
+
+``` js
+// ...
+mutations: {
+  INCREMENT (state, n) {
+    state.count += n
+  }
+}
+```
+``` js
+store.dispatch('INCREMENT', 10)
+```
+
+Aquí `10` será pasado al controlador de la mutación como el segundo argumento siguiendo `state`. Lo mismo para cualquier argumento adicional. Estos argumentos se denominan **carga útil** o "payload" para la mutación dada.
+
+### Despacho al estilo objeto
+
+> requiere >=0.6.2
+
+También puedes despachar mutaciones utilizando objetos:
+
+``` js
+store.dispatch({
+  type: 'INCREMENT',
+  payload: 10
+})
+```
+
+Ten en cuenta que cuando uses el estilo objeto debes incluir todos los argumentos como propiedades en el objeto despachado. El objeto entero será pasado como el segundo argumento a los manipuladores de mutación:
+
+``` js
+mutations: {
+  INCREMENT (state, mutation) {
+    state.count += mutation.payload
+  }
+}
+```
+
+### Despacho silencioso
+
+> requiere >=0.6.3
+
+En algunos casos puede que no desees que los middlewares registren el cambio de estado. Múltiples despachos al almacén en un período corto o encuestados no siempre tienen que ser rastreados. En estas situaciones puede considerarse apropiado silenciar las mutaciones.
+
+*Nota:* Esto debería evitarse cuando sea necesario. Las mutaciones silenciosas rompen el contrato de todos los cambios de estado siendo rastreados por el devtool. Utilizar con moderación y cuando sea absolutamente necesario.
+
+Despachar sin golpear middlewares se puede lograr con un indicador `silent`.
+
+``` js
+/**
+ * Ejemplo: Acción de progreso.
+ * Despacha a menudo cambios que no necesariamente deben ser rastreados
+ **/
+export function start(store, options = {}) {
+  let timer = setInterval(() => {
+    store.dispatch({
+      type: INCREMENT,
+      silent: true,
+      payload: {
+        amount: 1,
+      },
+    });
+    if (store.state.progress === 100) {
+      clearInterval(timer);
+    }
+  }, 10);
+}
+```
+
+### Las mutaciones siguen las reglas de reactividad de Vue
+
+Dado que el estado de almacenes Vuex es hecho reactivo por Vue, cuando mutamos el estado, componentes Vue que estén observando el estado se actualizarán automáticamente. Esto también significa que las mutaciones Vuex están sujetas a las mismas advertencias de reactividad que cuando se trabaja con Vue a secas:
+
+1. Prefiere inicializar el estado inicial de tu almacén con todos los campos deseados por adelantado.
+
+2. Cuando se añaden nuevas propiedades a un Objeto, deberás:
+
+  - Usar `Vue.set(obj, 'newProp', 123)`, o -
+
+  - Sustituir ese Objeto con uno nuevo. Por ejemplo, usando la etapa-2 [sintaxis de objetos de propagación](https://github.com/sebmarkbage/ecmascript-rest-spread) podemos escribirla así:
+
+  ``` js
+  state.obj = { ...state.obj, newProp: 123 }
+  ```
+
+### Usando constantes para los nombres de mutación
+
+También es común el uso de constantes para los nombres de mutación - permiten al código tomar ventaja de herramientas como linters, y poniendo todas las constantes en un archivo único permite a tus colaboradores obtener de un vistazo qué mutaciones son posibles en toda la aplicación:
+
+``` js
+// mutation-types.js
+export const SOME_MUTATION = 'SOME_MUTATION'
+```
+
+``` js
+// store.js
+import Vuex from 'vuex'
+import { SOME_MUTATION } from './mutation-types'
+
+const store = new Vuex.Store({
+  state: { ... },
+  actions: { ... },
+  mutations: {
+    // podemos utilizar la función nombre de propiedad computerizada del ES2015
+    // para usar una constante como el nombre de la función
+    [SOME_MUTATION] (state) {
+      // mutar estado
+    }
+  }
+})
+```
+
+Utilizar constantes es en gran parte una preferencia - puede ser útil en grandes proyectos con muchos desarrolladores, pero es totalmente opcional si no te gustan.
+
+### Las mutaciones deben ser síncronas
+
+Una regla importante a recordar es que **las funciones de controlador de mutación deben ser síncronas**. ¿Por qué? Considera el siguiente ejemplo:
+
+``` js
+mutations: {
+  SOME_MUTATION (state) {
+    api.callAsyncMethod(() => {
+      state.count++
+    })
+  }
+}
+```
+
+Ahora imaginemos que estamos depurando la app y mirando nuestros registros de mutación. Por cada mutación anotada, queremos ser capaces de comparar capturas de estado *antes* y *después* de la mutación. Sin embargo, la retrollamada asíncrona dentro de la mutación del ejemplo anterior lo hace imposible: la retrollamada no es ejecutada todavía cuando la mutación es despachada, y no sabemos cuándo la retrollamada será realmente ejecutada. Cualquier mutación de estado realizada en la retrollamada es esencialmente no rastreable!
+
+### Sobre acciones
+
+Asincronía combinada con mutación de estado puede hacer que tu programa sea muy difícil de razonar. Por ejemplo, cuando llames a dos métodos los dos con devoluciones de llamada asíncronas que mutan el estado, ¿cómo sabes cuando son llamadas y cual retrollamada se ejecutó primero? Esto es exactamente por lo que queremos separar los dos conceptos. En Vuex, llevamos a cabo todas las mutaciones de estado de manera síncrona. Realizaremos todas las operaciones asíncronas dentro de [acciones](actions.md).

+ 156 - 0
docs/es/state.md

@@ -0,0 +1,156 @@
+# Estado y obtenedores
+
+### Árbol de único estado
+
+Vuex utiliza un **árbol de único estado** - es decir, este único objeto contiene todo el estado a nivel de aplicación y sirve como la "única fuente de la verdad". Esto también significa que por lo general vas a tener sólo un almacén para cada aplicación. Un árbol de único estado hace que sea fácil de localizar una parte específica del estado, y nos permite tomar fácilmente instantáneas del estado actual de la aplicación para fines de depuración.
+
+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.
+
+### Obteniendo el estado Vuex en componentes Vue
+
+Entonces, ¿cómo mostrar el estado del almacén en nuestros componentes Vue? Ya que los almacenes Vuex son reactivos, la forma más sencilla de "recuperar" un estado del mismo es simplemente devolviendo un estado desde una [propiedad computarizada](http://vuejs.org/guide/computed.html):
+
+``` js
+// en la definición del componente Vue
+computed: {
+  count: function () {
+    return store.state.count
+  }
+}
+```
+
+Siempre que `store.state.count` cambie, hará que la propiedad computarizada sea reevaluada, y active las actualizaciones de DOM asociadas.
+
+Sin embargo, este modelo implica que el componente dependa de un almacén global. Eso hace que sea más difícil testear el componente, y también que sea difícil ejecutar varias instancias de la aplicación utilizando el mismo conjunto de componentes. En aplicaciones de gran tamaño, es posible que queramos "inyectar" el almacén en componentes hijos desde el componente raíz. He aquí cómo hacerlo:
+
+1. Instala Vuex y conecta tu componente raíz al almacén:
+
+  ``` js
+  import Vue from 'vue'
+  import Vuex from 'vuex'
+  import store from './store'
+  import MyComponent from './MyComponent'
+
+  // importante, enseña al componente Vue
+  // cómo manejar opciones relacionadas con Vuex
+  Vue.use(Vuex)
+
+  var app = new Vue({
+    el: '#app',
+    // proporciona el almacén utilizando la opción "store".
+    // esto inyectará la instancia del almacén a todos los componentes hijos.
+    store,
+    components: {
+      MyComponent
+    }
+  })
+  ```
+
+  Al proveer la opción `store` a la instancia raíz, el almacén será inyectado a todos sus componentes hijos y estará disponible en ellos como `this.$store`. Sin embargo, es poco probable que vayamos a necesitar referenciarlo.
+
+2. Dentro de los componentes hijos, recupera el estado con funciones **obtenedor** en la opción `vuex.getters`:
+
+  ``` js
+  // MyComponent.js
+  export default {
+    template: '...',
+    data () { ... },
+    // aquí es donde recuperamos el estado del almacén
+    vuex: {
+      getters: {
+        // una función obtenedor del almacén, que
+        // asigna `store.state.count` en el componente como `this.count`
+        count: function (state) {
+          return state.count
+        }
+      }
+    }
+  }
+  ```
+
+  Nota el bloque de opción especial `vuex`. Aquí es donde especificamos el estado que el componente va a utilizar del almacén. Para cada nombre de propiedad, especificamos una función obtenedor que recibe todo el árbol del almacén como único argumento, y entonces selecciona y devuelve parte del estado, o un valor computarizado derivado del estado. El resultado devuelto será establecido en el componente utilizando el nombre de la propiedad, al igual que una propiedad computarizada.
+
+  En muchos casos, la función "obtenedor" puede ser muy sucinta usando las funciones de dirección del ES2015:
+
+  ``` js
+  vuex: {
+    getters: {
+      count: state => state.count
+    }
+  }
+  ```
+
+### Obtenedores deben ser puros
+
+Todos los obtenedores de Vuex deben ser [funciones puras](https://en.wikipedia.org/wiki/Pure_function) - las mismas toman todo el árbol del estado, y devuelven algún valor basado exclusivamente en ese estado. Esto los hace más testeables, componibles y eficientes. También significa que **no puedes apoyarte en `this` dentro de obtenedores**.
+
+Si necesitas acceso a `this`, por ejemplo para calcular el estado derivado basado en el estado local o los props del componente, es necesario definir propiedades computarizadas, llanas por separado:
+
+``` js
+vuex: {
+  getters: {
+    currentId: state => state.currentId
+  }
+},
+computed: {
+  isCurrent () {
+    return this.id === this.currentId
+  }
+}
+```
+
+### Obtenedores pueden devolver estado derivado
+
+Obtenedores de estado Vuex son, en el fondo, propiedades computarizadas, esto significa que puedes apoyarte en ellos para que de manera reactiva (y eficiente) calculen un estado derivado. Por ejemplo, digamos que en el estado tenemos una colección `messages` que contienen todos los mensajes, y un `currentThreadID` representando el hilo que está siendo visto por el usuario. Lo que queremos mostrar al usuario es una lista filtrada de mensajes que pertenecen al hilo actual:
+
+``` js
+vuex: {
+  getters: {
+    filteredMessages: state => {
+      return state.messages.filter(message => {
+        return message.threadID === state.currentThreadID
+      })
+    }
+  }
+}
+```
+
+Dado que las propiedades computarizadas de Vue.js se almacenan en caché de forma automática y sólo reevaluadas cuando una dependencia reactiva cambie, no necesitas preocuparte de que esta función sea llamada en cada mutación.
+
+### Compartiendo obtenedores a través de múltiples componentes
+
+Como puedes ver, el obtenedor `filteredMessages` puede ser útil dentro de múltiples componentes. En ese caso, es una buena idea compartir la misma función entre ellos:
+
+``` js
+// getters.js
+export function filteredMessages (state) {
+  return state.messages.filter(message => {
+    return message.threadID === state.currentThreadID
+  })
+}
+```
+
+``` js
+// en un componente...
+import { filteredMessages } from './getters'
+
+export default {
+  vuex: {
+    getters: {
+      filteredMessages
+    }
+  }
+}
+```
+
+Debido a que los obtenedores son puros, los obtenedores compartidos a través de múltiples componentes se almacenan en caché de manera eficiente: cuando cambian las dependencias, sólo son reevaluados una vez para todos los componentes que los utilizan.
+
+> Referencias Flux: obtenedores Vuex pueden ser aproximadamente comparados con [`mapStateToProps`](https://github.com/rackt/react-redux/blob/master/docs/api.md#connectmapstatetoprops-mapdispatchtoprops-mergeprops-options) en Redux. Sin embargo, debido a que se apoyan en propiedades computarizadas de Vue, son más eficientes que `mapStateToProps`, y más similares a [reselect](https://github.com/reactjs/reselect).
+
+### A los componentes no se les permite mutar directamente el estado
+
+Es importante recordar que los **componentes nunca deberían mutar el estado del almacén Vuex directamente**. Porque queremos que toda mutación de estado sea explícita y rastreable, todas las mutaciones de estado del almacén Vuex deben llevarse a cabo dentro de los manipuladores de mutación del almacén.
+
+Para ayudar a imponer esta regla, cuando en [Modo estricto](strict.md), si el estado de almacén es mutado fuera de sus manipuladores de mutación, Vuex mostrará un error.
+
+Con esta regla en lugar, nuestros componentes Vue ahora tienen mucha menos responsabilidad: están conectados al estado del almacén Vuex a través de obtenedores de sólo lectura, y la única manera que tienen de afectar el estado es activando de alguna manera **mutaciones** (que veremos más adelante). Aún pueden poseer y operar en su estado local si es necesario, pero ya no ponemos ninguna lógica de data-fetching o mutación de estado global dentro de los componentes individuales. Ellos ahora están centralizados y manejados dentro de archivos relacionados con Vuex, lo que hace grandes aplicaciones más fáciles de entender y mantener.

+ 25 - 0
docs/es/strict.md

@@ -0,0 +1,25 @@
+# Modo estricto
+
+Para activar el modo estricto, simplemente establece `strict: true` al crear un almacén Vuex:
+
+``` js
+const store = new Vuex.Store({
+  // ...
+  strict: true
+})
+```
+
+En modo estricto, cada vez que el estado Vuex es mutado fuera de los manipuladores de mutación, un error será emitido. Esto asegura que todas las mutaciones del estado pueden ser explícitamente rastreadas por las herramientas de depuración.
+
+### Desarrollo frente a producción
+
+**¡No actives el modo estricto cuando compiles para producción!** El modo estricto ejecuta una observación en profundidad del árbol de estado para detectar mutaciones inapropiadas - asegúrate de apagarlo en producción para evitar el costo de rendimiento.
+
+Al igual que con middlewares, podemos dejar que las herramientas de compilación lo manejen:
+
+``` js
+const store = new Vuex.Store({
+  // ...
+  strict: process.env.NODE_ENV !== 'production'
+})
+```

+ 136 - 0
docs/es/structure.md

@@ -0,0 +1,136 @@
+# Estructura de la aplicación
+
+Vuex en realidad no restringe la forma de estructurar tu código. Más bien, hace cumplir un conjunto de principios de alto nivel:
+
+1. El estado de la aplicación es retenido en el almacén, como un solo objeto.
+
+2. La única forma de mutar el estado es despachando mutaciones en el almacén.
+
+3. Las mutaciones deben ser síncronas, y los únicos efectos secundarios que producen debería ser mutar el estado.
+
+4. Podemos exponer una API de mutación de estado más expresiva mediante la definición de acciones. Las acciones pueden encapsular lógica asincrónica como ir a buscar los datos, y los únicos efectos secundarios que producen debería ser despachar mutaciones.
+
+5. Los componentes utilizan obtenedores para recuperar el estado del almacén, y llaman acciones para mutar el estado.
+
+Lo bueno de las mutaciones Vuex, acciones y obtenedores es que **todos ellos son simplemente funciones**. Mientras sigas estas reglas, depende de ti cómo estructurar tu proyecto. Sin embargo, es bueno tener algunas convenciones para que puedas familiarizarte al instante con otro proyecto que utilice Vuex, así que aquí tienes algunas estructuras recomendadas en función de la escala de tu aplicación.
+
+### Proyecto simple
+
+Para un proyecto sencillo, simplemente podemos definir el **almacén** y las **acciones** en los archivos respectivos:
+
+``` bash
+.
+├── index.html
+├── main.js
+├── components
+│   ├── App.vue
+│   └── ...
+└── vuex
+    ├── store.js     # exporta el almacén (con el estado inicial y mutaciones)
+    └── actions.js   # exporta todas las acciones
+```
+
+Para un ejemplo real, echa un vistazo al [ejemplo Contador](https://github.com/vuejs/vuex/tree/master/examples/counter) o al [ejemplo TodoMVC](https://github.com/vuejs/vuex/tree/master/examples/todomvc).
+
+Como alternativa, también puedes separar las mutaciones en su propio archivo.
+
+### Proyecto mediano o grande
+
+Para cualquier aplicación no trivial, es probable que queramos seguir dividiendo aún más el código relacionado con Vuex en múltiples "módulos" (más o menos comparable a "almacenes" en vainilla Flux, y "reductores" en Redux), cada uno dedicado a un dominio específico de nuestra aplicación. Cada módulo estaría administrando un sub-árbol del estado, exportando el estado inicial para ese sub-árbol y todas las mutaciones que operan en ese sub-árbol:
+
+``` bash
+├── index.html
+├── main.js
+├── api
+│   └── ... # abstracciones para hacer solicitudes de API
+├── components
+│   ├── App.vue
+│   └── ...
+└── vuex
+    ├── actions.js        # exporta todas las acciones
+    ├── store.js          # donde montamos los módulos y exportamos el almacén
+    ├── mutation-types.js # constantes
+    └── modules
+        ├── cart.js       # estado y mutaciones para el carro
+        └── products.js   # estado y mutaciones para los productos
+```
+
+Un módulo típico luce así:
+
+``` js
+// vuex/modules/products.js
+import {
+  RECEIVE_PRODUCTS,
+  ADD_TO_CART
+} from '../mutation-types'
+
+// estado inicial
+const state = {
+  all: []
+}
+
+// mutaciones
+const mutations = {
+  [RECEIVE_PRODUCTS] (state, products) {
+    state.all = products
+  },
+
+  [ADD_TO_CART] (state, productId) {
+    state.all.find(p => p.id === productId).inventory--
+  }
+}
+
+export default {
+  state,
+  mutations
+}
+```
+
+Y en `vuex/store.js`, "ensamblamos" múltiples módulos juntos para crear la instancia Vuex:
+
+``` js
+// vuex/store.js
+import Vue from 'vue'
+import Vuex from '../../../src'
+// importa partes de los módulos
+import cart from './modules/cart'
+import products from './modules/products'
+
+Vue.use(Vuex)
+
+export default new Vuex.Store({
+  // combina sub-módulos
+  modules: {
+    cart,
+    products
+  }
+})
+```
+
+Aquí, el estado inicial del módulo `cart` será adjuntado al árbol raíz del estado como `store.state.cart`. Además, **todas las mutaciones definidas en un sub-módulo solamente reciben el estado del sub-árbol al que están asociadas**. Así mutaciones definidas en el módulo `cart` recibirán `store.state.cart` como primer argumento.
+
+La raíz del estado del sub-árbol es insustituible dentro del propio módulo. Por ejemplo esto no funcionará:
+
+``` js
+const mutations = {
+  SOME_MUTATION (state) {
+    state = { ... }
+  }
+}
+```
+
+En su lugar, siempre almacena el estado concreto como una propiedad de la raíz del sub-árbol:
+
+``` js
+const mutations = {
+  SOME_MUTATION (state) {
+    state.value = { ... }
+  }
+}
+```
+
+Dado que todos los módulos simplemente exportan objetos y funciones, son bastante fáciles de probar y mantener, y pueden ser recargados en vivo. También eres libre de alterar los patrones utilizados aquí para encontrar una estructura que se adapte a tus preferencias.
+
+Ten en cuenta que no ponemos las acciones en módulos, ya que una sola acción puede despachar mutaciones que afectan a múltiples módulos. Es también una buena idea desacoplar las acciones de la forma del estado y los detalles de implementación de mutaciones para una mejor separación de los cometidos. Si el archivo de acciones se hace demasiado grande, podemos convertirlo en una carpeta y separar las implementaciones de acciones asíncronas largas en archivos individuales.
+
+Para un ejemplo real, echa un vistazo al [ejemplo Carrito](https://github.com/vuejs/vuex/tree/master/examples/shopping-cart).

+ 167 - 0
docs/es/testing.md

@@ -0,0 +1,167 @@
+# Probando
+
+Las partes principales por las que queremos pasar las unidades de prueba en Vuex son mutaciones y acciones.
+
+### Probando las mutaciones
+
+Las mutaciones son muy fáciles de probar, ya que son sólo funciones que dependen completamente de sus argumentos. Un truco es que si estás usando módulos ES2015 y pones tus mutaciones dentro de tu archivo `store.js`, en adición a la exportación por defecto, también puedes exportar las mutaciones como una exportación nombrada:
+
+``` js
+const state = { ... }
+
+// exporta las mutaciones como una exportación nombrada
+export const mutations = { ... }
+
+export default new Vuex.Store({
+  state,
+  mutations
+})
+```
+
+Ejemplo probando una mutación usando Mocha + Chai (puedes utilizar cualquier biblioteca/aserción que quieras):
+
+``` js
+// mutations.js
+export const INCREMENT = state => state.count++
+```
+
+``` js
+// mutations.spec.js
+import { expect } from 'chai'
+import { mutations } from './store'
+
+// asignación mutaciones destructurada
+const { INCREMENT } = mutations
+
+describe('mutations', () => {
+  it('INCREMENT', () => {
+    // estado simulado
+    const state = { count: 0 }
+    // aplicar mutación
+    INCREMENT(state)
+    // asegurar resultado
+    expect(state.count).to.equal(1)
+  })
+})
+```
+
+### Probando acciones
+
+Las acciones pueden ser un poco más complejas ya que pueden llamar APIs externas. Cuando probamos acciones, por lo general tenemos que hacer un cierto nivel de simulación - por ejemplo, podemos abstraer las llamadas a la API en un servicio y simular ese servicio dentro de nuestras pruebas. Con el fin de simular fácilmente las dependencias, podemos utilizar Webpack e [inject-loader](https://github.com/plasticine/inject-loader) para compilar nuestros archivos de pruebas.
+
+Ejemplo probando una acción asíncrona:
+
+``` js
+// actions.js
+import shop from '../api/shop'
+
+export const getAllProducts = ({ dispatch }) => {
+  dispatch('REQUEST_PRODUCTS')
+  shop.getProducts(products => {
+    dispatch('RECEIVE_PRODUCTS', products)
+  })
+}
+```
+
+``` js
+// actions.spec.js
+
+// usa la sintaxis 'require' para los cargadores en línea.
+// con inject-loader, esto devuelve un 'module factory'
+// que nos permite inyectar dependencias simuladas.
+import { expect } from 'chai'
+const actionsInjector = require('inject!./actions')
+
+// crea el módulo con nuestras simulaciones
+const actions = actionsInjector({
+  '../api/shop': {
+    getProducts (cb) {
+      setTimeout(() => {
+        cb([ /* mocked response */ ])
+      }, 100)
+    }
+  }
+})
+
+// helper para probar la acción con mutaciones esperadas
+const testAction = (action, args, state, expectedMutations, done) => {
+  let count = 0
+  // simular despacho
+  const dispatch = (name, ...payload) => {
+    const mutation = expectedMutations[count]
+    expect(mutation.name).to.equal(name)
+    if (payload) {
+      expect(mutation.payload).to.deep.equal(payload)
+    }
+    count++
+    if (count >= expectedMutations.length) {
+      done()
+    }
+  }
+  // llama a la acción con almacén y argumentos simulados
+  action({dispatch, state}, ...args)
+
+  // comprobar si no deberían haber sido despachadas mutaciones
+  if (count === 0) {
+    expect(expectedMutations.length).to.equal(0)
+    done()
+  }
+}
+
+describe('actions', () => {
+  it('getAllProducts', done => {
+    testAction(actions.getAllProducts, [], {}, [
+      { name: 'REQUEST_PRODUCTS' },
+      { name: 'RECEIVE_PRODUCTS', payload: [ /* respuesta simulada */ ] }
+    ], done)
+  })
+})
+```
+
+### Ejecutando pruebas
+
+Si tus mutaciones y acciones son correctamente escritos, las pruebas deberían no tener dependencia directa de las APIs de navegador después de una simulación apropiada. De esta manera puedes simplemente agrupar las pruebas con Webpack y ejecutarlas directamente en Node. Como alternativa, puedes usar `mocha-loader` o Karma + `karma-webpack` para ejecutar las pruebas en navegadores reales.
+
+#### Ejecutando en Node
+
+Crea la siguiente configuración webpack:
+
+``` js
+module.exports = {
+  entry: './test.js',
+  output: {
+    path: __dirname,
+    filename: 'test-bundle.js'
+  },
+  module: {
+    loaders: [
+      {
+        test: /\.js$/,
+        loader: 'babel',
+        exclude: /node_modules/
+      }
+    ]
+  },
+  babel: {
+    presets: ['es2015']
+  }
+}
+```
+
+Entonces:
+
+``` bash
+webpack
+mocha test-bundle.js
+```
+
+#### Ejecutando en navegadores
+
+1. Instala `mocha-loader`
+2. Cambia el `entry` de la configuración de Webpack anterior a `'mocha!babel!./test.js'`.
+3. Inicia `webpack-dev-server` utilizando la configuración
+4. Ves a `localhost:8080/webpack-dev-server/test-bundle`.
+
+#### Ejecutando en navegador con Karma + karma-webpack
+
+Consulta la configuración en la documentación de [vue-loader](http://vuejs.github.io/vue-loader/workflow/testing.html).

+ 265 - 0
docs/es/tutorial.md

@@ -0,0 +1,265 @@
+# Tutorial
+
+Vamos a construir una aplicación muy sencilla utilizando Vuex para entender cómo usarlo. Para este ejemplo, estamos construyendo una aplicación en la que pulsas un botón, e incrementa un contador.
+
+![Resultados finales](tutorial/result.png)
+
+Estamos utilizando este sencillo ejemplo para explicar los conceptos y los problemas que Vuex pretende resolver - cómo manejar una gran aplicación que utiliza varios componentes. Considere si este ejemplo utiliza tres componentes:
+
+### `components/App.vue`
+
+El componente raíz, que contiene otros dos componentes hijos:
+
+* `Display` para visualizar el valor actual del contador.
+* `Increment` que es un botón para aumentar el valor actual.
+
+```html
+<template>
+  <div>
+    <Display></Display>
+    <Increment></Increment>
+  </div>
+</template>
+
+<script>
+
+import Display from './Display.vue'
+import Increment from './Increment.vue'
+
+export default {
+  components: {
+    Display: Display,
+    Increment: Increment
+  }
+}
+</script>
+```
+
+### `components/Display.vue`
+
+```html
+<template>
+  <div>
+    <h3>Recuento es 0</h3>
+  </div>
+</template>
+
+<script>
+export default {
+}
+</script>
+```
+
+### `components/Increment.vue`
+
+```html
+<template>
+  <div>
+    <button>Incrementar +1</button>
+  </div>
+</template>
+
+<script>
+export default {
+}
+</script>
+```
+
+### Desafíos sin Vuex
+
+* `Increment` y `Display` no son conscientes el uno del otro, y no pueden pasar mensajes entre sí.
+* `App` tendrá que utilizar eventos y transmisiones para coordinar los dos componentes.
+* Dado que `App` está coordinando entre los dos componentes, los mismos no son reutilizables y fuertemente acoplados. La reestructuración de la aplicación podría romperlo.
+
+### El "flujo" de Vuex
+
+Estos son los pasos que se llevan a cabo en orden:
+
+![El flujo de Vuex](tutorial/vuex_flow.png)
+
+Esto puede parecer un poco excesivo para incrementar un contador. Pero ten en cuenta que estos conceptos funcionan bien en aplicaciones de mayor tamaño, mejorando la mantenibilidad y haciendo la aplicación más fácil de depurar y mejorar a largo plazo. Así que vamos a modificar nuestro código para utilizar Vuex.
+
+### Paso 1: Añadir un almacén
+
+El almacén contiene los datos de la aplicación. Todos los componentes leen los datos del almacén. Antes de comenzar, instala Vuex a través del npm:
+
+```
+$ npm install --save vuex
+```
+
+Crea un nuevo archivo en `vuex/store.js`
+
+```js
+import Vue from 'vue'
+import Vuex from 'vuex'
+
+// Haz Vue consciente de Vuex
+Vue.use(Vuex)
+
+// Crea un objeto conteniendo el estado inicial
+// para cuando la app es iniciada
+const state = {
+  // TODO: Configurar el estado inicial
+}
+
+// Crea un objeto almacenando varias mutaciones. Escribe la mutación
+const mutations = {
+  // TODO: Configura las mutaciones
+}
+
+// Combina el estado inicial y las mutaciones para crear un almacén Vuex
+// Este almacén puede puede vincularse a nuestra app
+export default new Vuex.Store({
+  state,
+  mutations
+})
+```
+
+Tenemos que hacer que nuestra aplicación sea consciente de este almacén. Para ello simplemente tenemos que modificar nuestro componente raíz.
+
+Edita `components/App.vue` y añade el almacén.
+
+```js
+import Display from './Display.vue'
+import Increment from './IncrementButton.vue'
+import store from '../vuex/store' // importa el almacén que acabamos de crear
+
+export default {
+  components: {
+    Display: Display,
+    Increment: Increment
+  },
+  store: store // hace que este y todos los componentes hijos sean conscientes del nuevo almacén
+}
+```
+
+> **Consejo**: Con ES6 y babel puedes escribirlo como
+>
+>     components: {
+>       Display,
+>       Increment,
+>     },
+>     store
+
+### Paso 2: Configurar la acción
+
+La acción es una función que se llama desde el componente. Las funciones de acción pueden desencadenar cambios en el almacén despachando la mutación correcta. Una acción también puede hablar con backends HTTP y leer otros datos del almacén antes de despachar actualizaciones.
+
+Crear un nuevo archivo en `vuex/actions.js` con una sola función `incrementCounter`.
+
+```js
+// Una acción recibirá el almacén como el primer argumento.
+// Puesto que sólo estamos interesados en el despacho (y opcionalmente el estado)
+// podemos tirar de esos dos parámetros con la función de desestructuración del ES6
+export const incrementCounter = function ({ dispatch, state }) {
+  dispatch('INCREMENT', 1)
+}
+```
+
+Y vamos a llamar a la acción desde nuestro componente `components/Increment.vue`.
+
+```html
+<template>
+  <div>
+    <button @click='increment'>Incrementar +1</button>
+  </div>
+</template>
+
+<script>
+import { incrementCounter } from '../vuex/actions'
+export default {
+  vuex: {
+    actions: {
+      increment: incrementCounter
+    }
+  }
+}
+</script>
+```
+
+Notar algunas cosas interesantes acerca de lo que acabamos de añadir.
+
+1. Tenemos un nuevo objeto `vuex.actions` que incluye la nueva acción.
+2. No especificamos qué almacén, objeto, estado, etc. Vuex se encarga de todo por nosotros.
+3. Podemos llamar la acción mediante `this.increment()` en cualquier método.
+4. También podemos llamar la acción utilizando el parámetro `@click` haciendo de `increment` un método regular del componente.
+5. La acción se llama `incrementCounter`, pero podemos utilizar cualquier nombre apropiado.
+
+### Paso 3: Configura el estado y las mutaciones
+
+En nuestro archivo `vuex/actions.js` despachamos la mutación `INCREMENT` pero no hemos escrito todavía cómo manejarla. Hagamos eso ahora.
+
+Edita `vuex/store.js`.
+
+```js
+const state = {
+  // Cuando la app es iniciada, count se establece en 0
+  count: 0
+}
+
+const mutations = {
+  // Una mutación recibe el estado actual como el primer argumento
+  // Puedes hacer cualquier modificación que desees dentro de esta función
+  INCREMENT (state, amount) {
+    state.count = state.count + amount
+  }
+}
+```
+
+### Paso 4: Obtener el valor en el componente
+
+Crea un nuevo archivo llamado `vuex/getters.js`.
+
+```js
+// Este captador es una función que solamente devuelve el recuento
+// Con ES6 también puedes escribirlo como:
+// export const getCount = state => state.count
+
+export function getCount (state) {
+  return state.count
+}
+```
+
+Esta función devuelve parte del objeto de estado que es de interés - el recuento actual. Ahora podemos utilizar este captador dentro del componente.
+
+Edita `components/Display.vue`
+
+```html
+<template>
+  <div>
+    <h3>Recuento es {{ counterValue }}</h3>
+  </div>
+</template>
+
+<script>
+import { getCount } from '../vuex/getters'
+export default {
+  vuex: {
+    getters: {
+      // notar que estás pasando la función en sí misma, y no el valor 'getCount()'
+      counterValue: getCount
+    }
+  }
+}
+</script>
+```
+
+Hay un nuevo objeto `vuex.getters` que pide que `counterValue` esté ligado al captador `getCount`. Hemos elegido nombres diferentes para demostrar que se pueden utilizar nombres que tengan sentido en el contexto de tu componente, no necesariamente el nombre del captador en sí mismo.
+
+Tal vez te estés preguntando - por qué hemos elegido utilizar un captador en lugar de acceder directamente el valor del estado. Este concepto es más bien una mejor práctica, y es más aplicable a una aplicación grande, que presenta varias distintivas ventajas:
+
+1. Quizás nos interese definir obtenedores con valores computados (piensa en totales, promedios, etc.).
+2. Muchos de los componentes en una aplicación más grande pueden usar la misma función del captador.
+3. Si el valor se mueve de digamos `store.count` a `store.counter.value` tendrías que actualizar un captador en lugar de docenas de componentes.
+
+Estos son algunos de los beneficios de usar obtenedores.
+
+### Paso 5: Siguientes pasos
+
+Si ejecutas la aplicación ahora, comprobarás que se comporta como se espera.
+
+Para ampliar tu conocimiento de Vuex, puedes intentar implementar los siguientes cambios en la app, como un ejercicio.
+
+* Agregar un botón de decremento.
+* Instala [VueJS Devtools](https://chrome.google.com/webstore/detail/vuejs-devtools/nhdogjmejiglipccpnnnanhbledajbpd?hl=es) y juega con las herramientas Vuex y observa las mutaciones que están siendo aplicadas.
+* Añade una entrada de texto en otro componente llamado `IncrementAmount` e introduce la cantidad que hay que sumar. Esto puede ser un poco complicado ya que los formulario en Vuex funcionan de forma ligeramente diferente. Lea la sección [Form Handling](forms.md) para más detalles.

二进制
docs/es/tutorial/result.png


二进制
docs/es/tutorial/vuex_flow.png


二进制
docs/es/vuex.png