diff --git a/docs/README.md b/docs/README.md
index 54d17dc7a..c75bb088a 100644
--- a/docs/README.md
+++ b/docs/README.md
@@ -4,11 +4,11 @@
Vuex is a **state management pattern + library** for Vue.js applications. It serves as a centralized store for all the components in an application, with rules ensuring that the state can only be mutated in a predictable fashion. It also integrates with Vue's official [devtools extension](https://github.com/vuejs/vue-devtools) to provide advanced features such as zero-config time-travel debugging and state snapshot export / import.
-### What is a "State Management Pattern"?
+## What is a "State Management Pattern"?
Let's start with a simple Vue counter app:
-``` js
+```js
new Vue({
// state
data () {
@@ -58,7 +58,7 @@ If you want to learn Vuex in an interactive way you can check out this [Vuex cou
![vuex](/vuex.png)
-### When Should I Use It?
+## When Should I Use It?
Vuex helps us deal with shared state management with the cost of more concepts and boilerplate. It's a trade-off between short term and long term productivity.
diff --git a/docs/api/README.md b/docs/api/README.md
index 517254c0a..49439f15b 100644
--- a/docs/api/README.md
+++ b/docs/api/README.md
@@ -6,7 +6,7 @@ sidebar: auto
## Vuex.Store
-``` js
+```js
import Vuex from 'vuex'
const store = new Vuex.Store({ ...options })
@@ -36,7 +36,7 @@ const store = new Vuex.Store({ ...options })
Register actions on the store. The handler function receives a `context` object that exposes the following properties:
- ``` js
+ ```js
{
state, // same as `store.state`, or local state if in modules
rootState, // same as `store.state`, only in modules
@@ -81,7 +81,7 @@ const store = new Vuex.Store({ ...options })
An object containing sub modules to be merged into the store, in the shape of:
- ``` js
+ ```js
{
key: {
state,
@@ -122,7 +122,7 @@ const store = new Vuex.Store({ ...options })
Turn the devtools on or off for a particular vuex instance. For instance passing false tells the Vuex store to not subscribe to devtools plugin. Useful for if you have multiple stores on a single page.
- ``` js
+ ```js
{
devtools: false
}
@@ -178,7 +178,7 @@ const store = new Vuex.Store({ ...options })
Subscribe to store mutations. The `handler` is called after every mutation and receives the mutation descriptor and post-mutation state as arguments.
- ``` js
+ ```js
const unsubscribe = store.subscribe((mutation, state) => {
console.log(mutation.type)
console.log(mutation.payload)
@@ -190,7 +190,7 @@ const store = new Vuex.Store({ ...options })
By default, new handler is added to the end of the chain, so it will be executed after other handlers that were added before. This can be overridden by adding `prepend: true` to `options`, which will add the handler to the beginning of the chain.
- ``` js
+ ```js
store.subscribe(handler, { prepend: true })
```
@@ -207,7 +207,7 @@ const store = new Vuex.Store({ ...options })
Subscribe to store actions. The `handler` is called for every dispatched action and receives the action descriptor and current store state as arguments.
The `subscribe` method will return an `unsubscribe` function, which should be called when the subscription is no longer needed. For example, when unregistering a Vuex module or before destroying a Vue component.
- ``` js
+ ```js
const unsubscribe = store.subscribeAction((action, state) => {
console.log(action.type)
console.log(action.payload)
@@ -219,7 +219,7 @@ const store = new Vuex.Store({ ...options })
By default, new handler is added to the end of the chain, so it will be executed after other handlers that were added before. This can be overridden by adding `prepend: true` to `options`, which will add the handler to the beginning of the chain.
- ``` js
+ ```js
store.subscribeAction(handler, { prepend: true })
```
@@ -229,7 +229,7 @@ const store = new Vuex.Store({ ...options })
Since 3.1.0, `subscribeAction` can also specify whether the subscribe handler should be called *before* or *after* an action dispatch (the default behavior is *before*):
- ``` js
+ ```js
store.subscribeAction({
before: (action, state) => {
console.log(`before action ${action.type}`)
@@ -244,7 +244,7 @@ const store = new Vuex.Store({ ...options })
Since 3.4.0, `subscribeAction` can also specify an `error` handler to catch an error thrown when an action is dispatched. The function will receive an `error` object as the third argument.
- ``` js
+ ```js
store.subscribeAction({
error: (action, state, error) => {
console.log(`error action ${action.type}`)
diff --git a/docs/guide/README.md b/docs/guide/README.md
index e277d520a..f473a1ac2 100644
--- a/docs/guide/README.md
+++ b/docs/guide/README.md
@@ -8,7 +8,7 @@ At the center of every Vuex application is the **store**. A "store" is basically
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
+## The Simplest Store
:::tip 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/)!
@@ -16,9 +16,9 @@ We will be using ES2015 syntax for code examples for the rest of the docs. If yo
After [installing](../installation.md) Vuex, let's create a store. It is pretty straightforward - just provide an initial state object, and some mutations:
-#### Vuex 3.x (for Vue 2)
+### Vuex 3.x (for Vue 2)
-``` js
+```js
import Vue from 'vue'
import Vuex from 'vuex'
@@ -36,9 +36,9 @@ const store = new Vuex.Store({
})
```
-#### Vuex 4.x (for Vue 3)
+### Vuex 4.x (for Vue 3)
-``` js
+```js
import { createStore } from 'vuex'
import { createApp } from 'vue'
@@ -56,7 +56,7 @@ app.use(store)
Now, you can access the state object as `store.state`, and trigger a state change with the `store.commit` method:
-``` js
+```js
store.commit('increment')
console.log(store.state.count) // -> 1
@@ -64,7 +64,7 @@ console.log(store.state.count) // -> 1
In order to have an access to `this.$store` property in your Vue components, you need to provide the created store to Vue instance. Vuex has a mechanism to "inject" the store into all child components from the root component with the `store` option:
-``` js
+```js
new Vue({
el: '#app',
store: store,
@@ -84,7 +84,7 @@ new Vue({
Now we can commit a mutation from component's method:
-``` js
+```js
methods: {
increment() {
this.$store.commit('increment')
diff --git a/docs/guide/actions.md b/docs/guide/actions.md
index 2ccc999f5..226cf9834 100644
--- a/docs/guide/actions.md
+++ b/docs/guide/actions.md
@@ -39,7 +39,7 @@ actions: {
}
```
-### Dispatching Actions
+## Dispatching Actions
Actions are triggered with the `store.dispatch` method:
@@ -98,7 +98,7 @@ actions: {
Note we are performing a flow of asynchronous operations, and recording the side effects (state mutations) of the action by committing them.
-### Dispatching Actions in Components
+## Dispatching Actions in Components
You can dispatch actions in components with `this.$store.dispatch('xxx')`, or use the `mapActions` helper which maps component methods to `store.dispatch` calls (requires root `store` injection):
@@ -121,7 +121,7 @@ export default {
}
```
-### Composing Actions
+## Composing Actions
Actions are often asynchronous, so how do we know when an action is done? And more importantly, how can we compose multiple actions together to handle more complex async flows?
diff --git a/docs/guide/forms.md b/docs/guide/forms.md
index eacf6e0b7..8ca558530 100644
--- a/docs/guide/forms.md
+++ b/docs/guide/forms.md
@@ -15,6 +15,7 @@ The "Vuex way" to deal with it is binding the ``'s value and call a metho
``` html
```
+
``` js
// ...
computed: {
@@ -40,13 +41,14 @@ mutations: {
}
```
-### Two-way Computed Property
+## Two-way Computed Property
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:
``` html
```
+
``` js
// ...
computed: {
diff --git a/docs/guide/getters.md b/docs/guide/getters.md
index 981901efc..576cf91cf 100644
--- a/docs/guide/getters.md
+++ b/docs/guide/getters.md
@@ -34,7 +34,7 @@ const store = new Vuex.Store({
})
```
-### Property-Style Access
+## Property-Style Access
The getters will be exposed on the `store.getters` object, and you access values as properties:
@@ -69,7 +69,7 @@ computed: {
Note that getters accessed as properties are cached as part of Vue's reactivity system.
-### Method-Style Access
+## Method-Style Access
You can also pass arguments to getters by returning a function. This is particularly useful when you want to query an array in the store:
@@ -88,7 +88,7 @@ store.getters.getTodoById(2) // -> { id: 2, text: '...', done: false }
Note that getters accessed via methods will run each time you call them, and the result is not cached.
-### The `mapGetters` Helper
+## The `mapGetters` Helper
The `mapGetters` helper simply maps store getters to local computed properties:
diff --git a/docs/guide/modules.md b/docs/guide/modules.md
index ff9e8e300..e09d6f8c6 100644
--- a/docs/guide/modules.md
+++ b/docs/guide/modules.md
@@ -6,7 +6,7 @@ Due to using a single state tree, all states of our application are contained in
To help with that, Vuex allows us to divide our store into **modules**. Each module can contain its own state, mutations, actions, getters, and even nested modules - it's fractal all the way down:
-``` js
+```js
const moduleA = {
state: () => ({ ... }),
mutations: { ... },
@@ -31,11 +31,11 @@ store.state.a // -> `moduleA`'s state
store.state.b // -> `moduleB`'s state
```
-### Module Local State
+## Module Local State
Inside a module's mutations and getters, the first argument received will be **the module's local state**.
-``` js
+```js
const moduleA = {
state: () => ({
count: 0
@@ -57,7 +57,7 @@ const moduleA = {
Similarly, inside module actions, `context.state` will expose the local state, and root state will be exposed as `context.rootState`:
-``` js
+```js
const moduleA = {
// ...
actions: {
@@ -72,7 +72,7 @@ const moduleA = {
Also, inside module getters, the root state will be exposed as their 3rd argument:
-``` js
+```js
const moduleA = {
// ...
getters: {
@@ -83,13 +83,13 @@ const moduleA = {
}
```
-### Namespacing
+## Namespacing
By default, actions, mutations and getters inside modules are still registered under the **global namespace** - this allows multiple modules to react to the same mutation/action type.
If you want your modules to be more self-contained or reusable, you can mark it as namespaced with `namespaced: true`. When the module is registered, all of its getters, actions and mutations will be automatically namespaced based on the path the module is registered at. For example:
-``` js
+```js
const store = new Vuex.Store({
modules: {
account: {
@@ -134,13 +134,13 @@ const store = new Vuex.Store({
Namespaced getters and actions will receive localized `getters`, `dispatch` and `commit`. In other words, you can use the module assets without writing prefix in the same module. Toggling between namespaced or not does not affect the code inside the module.
-#### Accessing Global Assets in Namespaced Modules
+### Accessing Global Assets in Namespaced Modules
If you want to use global state and getters, `rootState` and `rootGetters` are passed as the 3rd and 4th arguments to getter functions, and also exposed as properties on the `context` object passed to action functions.
To dispatch actions or commit mutations in the global namespace, pass `{ root: true }` as the 3rd argument to `dispatch` and `commit`.
-``` js
+```js
modules: {
foo: {
namespaced: true,
@@ -176,11 +176,11 @@ modules: {
}
```
-#### Register Global Action in Namespaced Modules
+### Register Global Action in Namespaced Modules
If you want to register global actions in namespaced modules, you can mark it with `root: true` and place the action definition to function `handler`. For example:
-``` js
+```js
{
actions: {
someOtherAction ({dispatch}) {
@@ -202,11 +202,11 @@ If you want to register global actions in namespaced modules, you can mark it wi
}
```
-#### Binding Helpers with Namespace
+### Binding Helpers with Namespace
When binding a namespaced module to components with the `mapState`, `mapGetters`, `mapActions` and `mapMutations` helpers, it can get a bit verbose:
-``` js
+```js
computed: {
...mapState({
a: state => state.some.nested.module.a,
@@ -227,7 +227,7 @@ methods: {
In such cases, you can pass the module namespace string as the first argument to the helpers so that all bindings are done using that module as the context. The above can be simplified to:
-``` js
+```js
computed: {
...mapState('some/nested/module', {
a: state => state.a,
@@ -248,7 +248,7 @@ methods: {
Furthermore, you can create namespaced helpers by using `createNamespacedHelpers`. It returns an object having new component binding helpers that are bound with the given namespace value:
-``` js
+```js
import { createNamespacedHelpers } from 'vuex'
const { mapState, mapActions } = createNamespacedHelpers('some/nested/module')
@@ -271,11 +271,11 @@ export default {
}
```
-#### Caveat for Plugin Developers
+### Caveat for Plugin Developers
You may care about unpredictable namespacing for your modules when you create a [plugin](plugins.md) that provides the modules and let users add them to a Vuex store. Your modules will be also namespaced if the plugin users add your modules under a namespaced module. To adapt this situation, you may need to receive a namespace value via your plugin option:
-``` js
+```js
// get namespace value via plugin option
// and returns Vuex plugin function
export function createPlugin (options = {}) {
@@ -287,11 +287,11 @@ export function createPlugin (options = {}) {
}
```
-### Dynamic Module Registration
+## Dynamic Module Registration
You can register a module **after** the store has been created with the `store.registerModule` method:
-``` js
+```js
import Vuex from 'vuex'
const store = new Vuex.Store({ /* options */ })
@@ -315,13 +315,13 @@ You can also remove a dynamically registered module with `store.unregisterModule
Note that you may check if the module is already registered to the store or not via `store.hasModule(moduleName)` method.
-#### Preserving state
+### Preserving state
It may be likely that you want to preserve the previous state when registering a new module, such as preserving state from a Server Side Rendered app. You can achieve this with `preserveState` option: `store.registerModule('a', module, { preserveState: true })`
When you set `preserveState: true`, the module is registered, actions, mutations and getters are added to the store, but the state is not. It's assumed that your store state already contains state for that module and you don't want to overwrite it.
-### Module Reuse
+## Module Reuse
Sometimes we may need to create multiple instances of a module, for example:
@@ -332,7 +332,7 @@ If we use a plain object to declare the state of the module, then that state obj
This is actually the exact same problem with `data` inside Vue components. So the solution is also the same - use a function for declaring module state (supported in 2.3.0+):
-``` js
+```js
const MyReusableModule = {
state: () => ({
foo: 'bar'
diff --git a/docs/guide/mutations.md b/docs/guide/mutations.md
index 14b3048bc..1c0ba8758 100644
--- a/docs/guide/mutations.md
+++ b/docs/guide/mutations.md
@@ -4,7 +4,7 @@
The only way to actually change state in a Vuex store is by committing a mutation. Vuex mutations are very similar to events: each mutation has a string **type** and a **handler**. The handler function is where we perform actual state modifications, and it will receive the state as the first argument:
-``` js
+```js
const store = new Vuex.Store({
state: {
count: 1
@@ -20,15 +20,15 @@ const store = new Vuex.Store({
You cannot directly call a mutation handler. Think of it more like event registration: "When a mutation with type `increment` is triggered, call this handler." To invoke a mutation handler, you need to call `store.commit` with its type:
-``` js
+```js
store.commit('increment')
```
-### Commit with Payload
+## Commit with Payload
You can pass an additional argument to `store.commit`, which is called the **payload** for the mutation:
-``` js
+```js
// ...
mutations: {
increment (state, n) {
@@ -36,13 +36,14 @@ mutations: {
}
}
```
-``` js
+
+```js
store.commit('increment', 10)
```
In most cases, the payload should be an object so that it can contain multiple fields, and the recorded mutation will also be more descriptive:
-``` js
+```js
// ...
mutations: {
increment (state, payload) {
@@ -51,17 +52,17 @@ mutations: {
}
```
-``` js
+```js
store.commit('increment', {
amount: 10
})
```
-### Object-Style Commit
+## Object-Style Commit
An alternative way to commit a mutation is by directly using an object that has a `type` property:
-``` js
+```js
store.commit({
type: 'increment',
amount: 10
@@ -70,7 +71,7 @@ store.commit({
When using object-style commit, the entire object will be passed as the payload to mutation handlers, so the handler remains the same:
-``` js
+```js
mutations: {
increment (state, payload) {
state.count += payload.amount
@@ -78,7 +79,7 @@ mutations: {
}
```
-### Mutations Follow Vue's Reactivity Rules
+## Mutations Follow Vue's Reactivity Rules
Since a Vuex store's state is made reactive by Vue, when we mutate the state, Vue components observing the state will update automatically. This also means Vuex mutations are subject to the same reactivity caveats when working with plain Vue:
@@ -90,20 +91,20 @@ Since a Vuex store's state is made reactive by Vue, when we mutate the state, Vu
- Replace that Object with a fresh one. For example, using the [object spread syntax](https://github.com/tc39/proposal-object-rest-spread) we can write it like this:
- ``` js
+ ```js
state.obj = { ...state.obj, newProp: 123 }
```
-### Using Constants for Mutation Types
+## Using Constants for Mutation Types
It is a commonly seen pattern to use constants for mutation types in various Flux implementations. This allows the code to take advantage of tooling like linters, and putting all constants in a single file allows your collaborators to get an at-a-glance view of what mutations are possible in the entire application:
-``` js
+```js
// mutation-types.js
export const SOME_MUTATION = 'SOME_MUTATION'
```
-``` js
+```js
// store.js
import Vuex from 'vuex'
import { SOME_MUTATION } from './mutation-types'
@@ -122,11 +123,11 @@ const store = new Vuex.Store({
Whether to use constants is largely a preference - it can be helpful in large projects with many developers, but it's totally optional if you don't like them.
-### Mutations Must Be Synchronous
+## Mutations Must Be Synchronous
One important rule to remember is that **mutation handler functions must be synchronous**. Why? Consider the following example:
-``` js
+```js
mutations: {
someMutation (state) {
api.callAsyncMethod(() => {
@@ -138,11 +139,11 @@ mutations: {
Now imagine we are debugging the app and looking at the devtool's mutation logs. For every mutation logged, the devtool will need to capture a "before" and "after" snapshots of the state. However, the asynchronous callback inside the example mutation above makes that impossible: the callback is not called yet when the mutation is committed, and there's no way for the devtool to know when the callback will actually be called - any state mutation performed in the callback is essentially un-trackable!
-### Committing Mutations in Components
+## Committing Mutations in Components
You can commit mutations in components with `this.$store.commit('xxx')`, or use the `mapMutations` helper which maps component methods to `store.commit` calls (requires root `store` injection):
-``` js
+```js
import { mapMutations } from 'vuex'
export default {
@@ -161,11 +162,11 @@ export default {
}
```
-### On to Actions
+## On to Actions
Asynchronicity combined with state mutation can make your program very hard to reason about. For example, when you call two methods both with async callbacks that mutate the state, how do you know when they are called and which callback was called first? This is exactly why we want to separate the two concepts. In Vuex, **mutations are synchronous transactions**:
-``` js
+```js
store.commit('increment')
// any state change that the "increment" mutation may cause
// should be done at this moment.
diff --git a/docs/guide/plugins.md b/docs/guide/plugins.md
index b96818e4b..db66d12fb 100644
--- a/docs/guide/plugins.md
+++ b/docs/guide/plugins.md
@@ -4,7 +4,7 @@
Vuex stores accept the `plugins` option that exposes hooks for each mutation. A Vuex plugin is simply a function that receives the store as the only argument:
-``` js
+```js
const myPlugin = store => {
// called when the store is initialized
store.subscribe((mutation, state) => {
@@ -16,20 +16,20 @@ const myPlugin = store => {
And can be used like this:
-``` js
+```js
const store = new Vuex.Store({
// ...
plugins: [myPlugin]
})
```
-### Committing Mutations Inside Plugins
+## Committing Mutations Inside Plugins
Plugins are not allowed to directly mutate state - similar to your components, they can only trigger changes by committing mutations.
By committing mutations, a plugin can be used to sync a data source to the store. For example, to sync a websocket data source to the store (this is just a contrived example, in reality the `createWebSocketPlugin` function can take some additional options for more complex tasks):
-``` js
+```js
export default function createWebSocketPlugin (socket) {
return store => {
socket.on('data', data => {
@@ -44,7 +44,7 @@ export default function createWebSocketPlugin (socket) {
}
```
-``` js
+```js
const plugin = createWebSocketPlugin(socket)
const store = new Vuex.Store({
@@ -54,11 +54,11 @@ const store = new Vuex.Store({
})
```
-### Taking State Snapshots
+## Taking State Snapshots
Sometimes a plugin may want to receive "snapshots" of the state, and also compare the post-mutation state with pre-mutation state. To achieve that, you will need to perform a deep-copy on the state object:
-``` js
+```js
const myPluginWithSnapshot = store => {
let prevState = _.cloneDeep(store.state)
store.subscribe((mutation, state) => {
@@ -74,7 +74,7 @@ const myPluginWithSnapshot = store => {
**Plugins that take state snapshots should be used only during development.** When using webpack or Browserify, we can let our build tools handle that for us:
-``` js
+```js
const store = new Vuex.Store({
// ...
plugins: process.env.NODE_ENV !== 'production'
@@ -85,13 +85,13 @@ const store = new Vuex.Store({
The plugin will be used by default. For production, you will need [DefinePlugin](https://webpack.js.org/plugins/define-plugin/) for webpack or [envify](https://github.com/hughsk/envify) for Browserify to convert the value of `process.env.NODE_ENV !== 'production'` to `false` for the final build.
-### Built-in Logger Plugin
+## Built-in Logger Plugin
> If you are using [vue-devtools](https://github.com/vuejs/vue-devtools) you probably don't need this.
Vuex comes with a logger plugin for common debugging usage:
-``` js
+```js
import { createLogger } from 'vuex'
const store = new Vuex.Store({
@@ -105,7 +105,7 @@ Before v3.5.0, the `createLogger` function is exported at `vuex/dist/logger` pac
The `createLogger` function takes a few options:
-``` js
+```js
const logger = createLogger({
collapsed: false, // auto-expand logged mutations
filter (mutation, stateBefore, stateAfter) {
@@ -142,11 +142,11 @@ The logger file can also be included directly via a `
```
-### NPM
+## NPM
-``` bash
+```bash
npm install vuex --save
# If using Vue 3.0 + Vuex 4.0:
npm install vuex@next --save
```
-### Yarn
+## Yarn
-``` bash
+```bash
yarn add vuex
# If using Vue 3.0 + Vuex 4.0:
@@ -35,19 +35,18 @@ yarn add vuex@next --save
When used with a module system, you must explicitly install Vuex as a plugin:
+### With Vue 2
-#### With Vue 2
-
-``` js
+```js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
```
-#### With Vue 3
+### With Vue 3
-``` js
+```js
import { createApp } from 'vue'
import { createStore } from 'vuex'
@@ -59,13 +58,13 @@ app.use(store)
You don't need to do this when using global script tags.
-### Promise
+## Promise
Vuex requires [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Using_promises). If your supporting browsers do not implement Promise (e.g. IE), you can use a polyfill library, such as [es6-promise](https://github.com/stefanpenner/es6-promise).
You can include it via CDN:
-``` html
+```html
```
@@ -73,22 +72,22 @@ Then `window.Promise` will be available automatically.
If you prefer using a package manager such as NPM or Yarn, install it with the following commands:
-``` bash
+```bash
npm install es6-promise --save # NPM
yarn add es6-promise # Yarn
```
Furthermore, add the below line into anywhere in your code before using Vuex:
-``` js
+```js
import 'es6-promise/auto'
```
-### Dev Build
+## Dev Build
You will have to clone directly from GitHub and build `vuex` yourself if you want to use the latest dev build.
-``` bash
+```bash
git clone https://github.com/vuejs/vuex.git node_modules/vuex
cd node_modules/vuex
npm install