Vuex 是什么?
Vuex 是一个专为 Vue.js 应用程序开发的状态管理器,采用 集中式存储 管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
Vue 核心概念
State
Vuex store 实例的根状态对象,用于定义共享的状态变量。
Getter
读取器,外部程序通过它获取变量的具体值,或者在取值前做一些计算(可以认为是 store 的计算属性)
Mutation
修改器,它只用于修改 state 中定义的状态变量。
Action
动作,向 store 发出调用通知,执行本地或者远端的某一个操作(可以理解为 store 的 methods)
Module
vuex 在 vue-cli 中的应用
第一步:npm 下载 vuex 资源包:
npm install vuex -S
第二步:在 src 下创建文件夹,在 src 下创建 store.js,官方推荐项目结构
store.js 文件
import Vue from ‘vue’
import Vuex from ‘vuex’
import * as getters from ‘./store/getters’ // 导入响应的模块,* 相当于引入了这个组件下所有导出的事例
import * as actions from ‘./store/actions’
import * as mutations from ‘./store/mutations’
Vue.use(Vuex)
// 首先声明一个需要全局维护的状态 state, 比如 titelName
const state = {
titelName: ‘ 小 A 的大标题 ’ // 默认值
// id: xxx 如果还有全局状态也可以在这里添加
// name:xxx
}
export default new Vuex.Store({
strict: process.env.NODE_ENV !== ‘production’, // 在严格模式下,无论何时发生了状态变更且不是由 mutation 函数引起的,将会抛出错误。这能保证所有的状态变更都能被调试工具跟踪到。不要在发布环境下启用严格模式以避免性能损失!
state, // 共同维护的一个状态,state 里面可以是很多个全局状态
getters, // 获取数据并渲染
actions, // 数据的异步操作
mutations // 处理数据的唯一途径,state 的改变或赋值只能在这里
})
getter.js 文件
// 获取最终的状态信息
export const titelName = state => state.titelName
actions.js 文件
// 给 action 注册事件处理函数。当这个函数被触发时候,将状态提交到 mutations 中处理
export function modifyAName({commit}, name) {// commit 提交;name 即为点击后传递过来的参数,此时是 ‘A 餐馆 ’
return commit(‘modifyAName’, name)
}
// export const modifyAName = ({commit},name) => commit(‘modifyAName’, name)
export const modifyBName = ({commit}, name) => commit(‘modifyBName’, name)
mutations.js 文件
// 提交 mutations 是更改 Vuex 状态的唯一合法方法
export const modifyAName = (state, name) => {
state.titelName = name // 把方法传递过来的参数,赋值给 state 中的 titelName
}
export const modifyBName = (state, name) => {
state.titelName = name
}
router.js 文件
import Vue from ‘vue’
import Router from ‘vue-router’
import Home from ‘./views/Home.vue’
import componentA from ‘./components/componentA.vue’
import componentB from ‘./components/componentB.vue’
Vue.use(Router)
export default new Router({
routes: [
{
path: ‘/’,
name: ‘home’,
component: Home
},
{
path: ‘/about’,
name: ‘about’,
// route level code-splitting
// this generates a separate chunk (about.[hash].js) for this route
// which is lazy-loaded when the route is visited.
component: () => import(/* webpackChunkName: “about” */ ‘./views/About.vue’)
},
{
path: ‘/componentA’,
name: ‘componentA’,
component: componentA
},
{
path: ‘/componentB’,
name: ‘componentB’,
component: componentB
},
]
})
componentA.vue 文件
<template>
<div>
<span>A 页面名字 </span>
<input type=”text” name id v-model=”titelName” @keydown=”modifyAName(titelName)”>
<button @click=”modifyAName(‘ssds’)”> 改标题 </button>
<button @click=”jump()”> 调到 B 页面 </button>
</div>
</template>
<script>
// import {mapActions, mapGetters} from “vuex”;
import {mapActions} from “vuex”;
export default {
data() {
return {};
},
methods: {
…mapActions([‘modifyAName’]), // 相当于 this.$store.dispatch(‘modifyName’), 提交这个方法
jump() {
this.$router.push(“componentB”);
}
},
computed: {
// 注意 v-model v-if
// …mapGetters([“titelName”])
titelName: {
get() {
return this.$store.state.titelName;
},
set(val) {
console.log(val);
this.$store.commit(‘modifyAName’, val);
// this.$store.dispatch(‘modifyAName’);
console.log(this.$store.state.titelName);
}
}
}
};
</script>
<style scoped>
</style>
componentB.vue 文件
<template>
<div>
<span>B 页面名字 </span>
<input type=”text” name id v-model=”titelName” @keydown=”modifyBName(titelName)”>
<button @click=”jump()”> 调到 A 页面 </button>
</div>
</template>
<script>
// import {mapActions, mapGetters} from “vuex”;
import {mapActions} from “vuex”;
export default {
data() {
return {};
},
methods: {
…mapActions(
//
[“modifyBName”]
),
jump() {
this.$router.push(“componentA”);
}
},
computed: {
// …mapGetters([“titelName”])
titelName: {
get: function() {
return this.$store.state.titelName;
},
set: function(val) {
this.$store.commit(“modifyBName”, val);
}
}
}
};
</script>
<style scoped>
</style>
// 第三步:在 src/main.js 中引入
import Vue from ‘vue’
import App from ‘./App.vue’
import router from ‘./router’
import store from ‘./store’
Vue.config.productionTip = false
new Vue({
router,
store,
render: h => h(App)
}).$mount(‘#app’)
如何在组件中去使用 vuex 的值和方法
直接获取、修改
//state
this.$store.state.count
//getter
this.$store.getters.count
// 调用 action 修改 state 值,不带参数
this.$store.dispatch(‘increment’);
// 调用 action 修改 state 值,带参数
this.$store.dispatch(‘increment’,{value :123});
通过 辅助函数 获取、修改 vuex
vuex 提供了三种辅助函数用于获取、修改 vuex:mapState、mapGetters、mapActions 即将 vuex 的变量或者方法映射到 vue 组件 this 指针上。
使用 state 获取共享变量
<script type=”text/javascript”>
import {mapState} from ‘vuex’
export default{
computed : {
…mapState([
‘count’,
‘buttonShow’
])
}
}
</script>
使用 getters 获取共享变量,
<script type=”text/javascript”>
import {mapGetters} from ‘vuex’
export default{
computed : {
…mapGetters([
‘count’,
‘buttonShow’
])
}
}
</script>
使用 actions 修改共享变量
<script type=”text/javascript”>
import {mapActions} from ‘vuex’
export default{
methods : {
…mapActions({increment:’increment’,decrement:’decrement’}),
}
}
</script>