Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。
它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
核心概念
store(仓库):每一个 Vuex 应用的核心就是 store(仓库)。“store”基本上就是一个容器,它包含着你的应用中大部分的状态 (state)。
mutations:修改 state 中的数据,mutations 方法的第一个形参,永远都是 state 对象
actions:主要是提供一些异步操作,调用mutation中的方法,来修改 state 中的数据
getter:定义一个 getters,今后页面上都可以直接输出这个 getters 对应的值
案例实现
使用 vue-cli 改造:
<template> <div> <!-- 直接访问 vuex 中的state 状态 - 不推荐使用 --> <h1>{{ $store.state.count }}</h1> <!-- 通过 计算属性 映射- 推荐使用 --> <h2>{{count}}-{{msg}}</h2> <h3>{{countInfo}}</h3> <!-- 同步 更改值 --> <div class="sync"> <button @click="addSyncHandler">同步加 +1</button> <button @click="addNSyncHandler(10)">同步加 +10</button> </div> <br /> <!-- 异步 更改值 --> <div class="async"> <button @click="addAsyncHandler">异步延时1s加 +1</button> <button @click="addNAsyncHandler(10)">异步延时1s加 +10</button> </div> </div> </template> <script> import { mapState, mapMutations, mapActions, mapGetters } from 'vuex' export default { computed: { // 映射 state 中的值 ...mapState(['count', 'msg']), // 映射 getters 中的 countInfo 方法 ...mapGetters(['countInfo']) }, methods: { // 映射 mutations 中的 同步方法 ...mapMutations(['addSyncHandler', 'addNSyncHandler']), // 映射 actions 中的 异步方法 ...mapActions(['addAsyncHandler', 'addNAsyncHandler']) } } </script> <style> .sync { padding: 10px; border: 2px solid red; } .async { padding: 10px; border: 2px solid blue; } </style>
<template> <div> <!-- 直接访问 vuex 中的state 状态 - 不推荐使用 --> <h1>{{ $store.state.count }}</h1> <!-- 通过 计算属性 映射- 推荐使用 --> <h2>{{count}}-{{msg}}</h2> <h3>{{countInfo}}</h3> <!-- 同步 更改值 --> <div class="sync"> <button @click="subSyncHandler">同步加 -1</button> <button @click="subNSyncHandler(10)">同步加 -10</button> </div> <br /> <!-- 异步 更改值 --> <div class="async"> <button @click="subAsyncHandler">异步延时1s加 -1</button> <button @click="subNAsyncHandler(10)">异步延时1s加 -10</button> </div> </div> </template> <script> import { mapState, mapMutations, mapActions, mapGetters } from 'vuex' export default { computed: { // 映射 state 中的值 ...mapState(['count', 'msg']), // 映射 getters 中的 countInfo 方法 ...mapGetters(['countInfo']) }, methods: { // 映射 mutations 中的 同步方法 ...mapMutations(['subSyncHandler', 'subNSyncHandler']), // 映射 actions 中的 异步方法 ...mapActions(['subAsyncHandler', 'subNAsyncHandler']) } } </script> <style> .sync { padding: 10px; border: 2px solid red; } .async { padding: 10px; border: 2px solid blue; } </style>
import Vue from 'vue' import Router from 'vue-router' import Add from '@/components/Add' import Sub from '@/components/Sub' Vue.use(Router) export default new Router({ routes: [ { path: '/', name: 'text', components: { add: Add, sub: Sub } } ] })
import Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex) export default new Vuex.Store({ // 全局共享数据的存储对象 // 所有在组件之间共享的数据,都应该挂载到 state 中 state: { count: 100, msg: '映射到组件中的值' }, // 注意:只有 mutations 中提供的方法,有权利修改 state 中的数据 mutations: { addSyncHandler(state) { state.count++ }, addNSyncHandler(state, step) { // vuex 官方推荐,不要直接在 mutations 中,执行异步操作,去修改state中的数据;否则 会让 调试工具运行紊乱; // 如果,涉及到 异步的 去修改 state 中的数据,那么一定要把 异步操作,定义到 actions 节点中; /* setTimeout(() => { state.count += step }, 1000) */ state.count += step }, // -1 的方法 subSyncHandler(state) { state.count-- }, subNSyncHandler(state, step) { state.count -= step } }, // actions 主要是提供一些异步操作,来修改 state 中的数据 actions: { // 提供一个 异步自增+1的方法 addAsyncHandler(context) { setTimeout(() => { context.commit('addSyncHandler') }, 1000) }, // 异步 +N addNAsyncHandler(context, step) { setTimeout(() => { context.commit('addNSyncHandler', step) }, 1000) }, // 异步 -1 subAsyncHandler(context) { setTimeout(() => { context.commit('subSyncHandler') }, 1000) }, // 异步 -N subNAsyncHandler(contenxt, step) { setTimeout(() => { contenxt.commit('subNSyncHandler', step) }, 1000) } }, // getters 类似于计算属性 getters: { // 定义一个 getters,今后页面上都可以直接输出 这个 getters 对应的值 countInfo(state) { // getters 有一个非常有用的特性: // 只要内部依赖的 state 上的数据,发生了变化,会重新计算 getters 的值 return `当前最新的count值为:${state.count}` } } })
<template> <div id="app"> <router-view name="add"/> <hr> <router-view name="sub"/> </div> </template> <script> export default { name: 'App' } </script>
import Vue from 'vue' import App from './App' import router from './router' import store from './vuex' Vue.config.productionTip = false /* eslint-disable no-new */ new Vue({ el: '#app', router, render: h => h(App), store })