From 6734ac5a47d3f8de6f7879dc44cf4d1d8898d4a4 Mon Sep 17 00:00:00 2001 From: Kia King Ishii Date: Mon, 12 Oct 2020 22:53:26 +0900 Subject: [PATCH] docs: make heading level semantically correct --- docs/README.md | 6 +++--- docs/api/README.md | 20 +++++++++---------- docs/guide/README.md | 16 +++++++-------- docs/guide/actions.md | 6 +++--- docs/guide/forms.md | 4 +++- docs/guide/getters.md | 6 +++--- docs/guide/modules.md | 44 ++++++++++++++++++++--------------------- docs/guide/mutations.md | 43 ++++++++++++++++++++-------------------- docs/guide/plugins.md | 26 ++++++++++++------------ docs/guide/state.md | 22 ++++++++++----------- docs/guide/strict.md | 6 +++--- docs/guide/structure.md | 2 +- docs/installation.md | 33 +++++++++++++++---------------- 13 files changed, 118 insertions(+), 116 deletions(-) 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