npm install vuex --save
Vuex是做什么的?
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。
它采用 集中式存储管理 应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
Vuex 也集成到 Vue 的官方调试工具 devtools extension,提供了诸如零配置的 time-travel 调试、状态快照导入导出等高级调试功能。
状态管理到底是什么?
其实,你可以简单的将其看成把需要多个组件共享的变量全部存储在一个对象里面。
然后,将这个对象放在顶层的Vue实例中,让其他组件可以使用。
Vuex状态管理图例
简单的案例
这里,我们先在src下创建一个文件夹store,并且在其中创建一个index.js文件 在index.js文件中写入如下代码:
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const store=new Vuex.Store({
state:{
counter:1000
},
mutations:{
//方法
increment(state){
state.counter++
},
decrement(state){
state.counter--
}
},
actions:{
},
getters:{
},
modules:{
}
})
export default store
挂载到Vue实例中
我们让所有的Vue组件都可以使用这个store对象
来到main.js文件,导入store对象,并且放在new Vue中
这样,在其他Vue组件中,我们就可以通过this.$store的方式,获取到这个store对象了
import Vue from 'vue'
import App from './App'
import store from './store/index.js'
Vue.config.productionTip = false
/* eslint-disable no-new */
new Vue({
el: '#app',
store,
render: h => h(App)
})
使用Vuex的count
<template>
<div id="app">
<!-- <h2>{{message}}</h2> -->
<h1>app={{$store.state.counter}}</h1>
<button @click="addtion">+</button>
<button @click="subtraction">-</button>
<hello-vuex />
</div>
</template>
<script>
import HelloVuex from "./components/HelloVuex.vue"
export default {
name: 'App',
data(){
return{
message:'我是App组件'
}
},
methods:{
addtion(){
this.$store.commit('increment')
},
subtraction(){
this.$store.commit('decrement')
}
},
components: {
HelloVuex
}
}
</script>
<style>
</style>
通过this.$store.state.属性的方式来访问状态
通过this.$store.commit('mutation中方法')来修改状态
Vuex核心概念
State单一状态树
如果你的状态信息是保存到多个Store对象中的,那么之后的管理和维护等等都会变得特别困难。
所以Vuex也使用了单一状态树来管理应用层级的全部状态。
单一状态树能够让我们最直接的方式找到某个状态的片段,而且在之后的维护和调试过程中,也可以非常方便的管理和维护。
Getters基本使用
index.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const store=new Vuex.Store({
state:{
counter:1000,
students:[
{id:100,name:"苹苹",age:21},
{id:101,name:"晴晴",age:11},
{id:102,name:"金金",age:21},
{id:103,name:"憨憨",age:1}
]
},
mutations:{
//方法
increment(state){
state.counter++
},
decrement(state){
state.counter--
}
},
actions:{
},
getters:{
powerCounter(state){
return state.counter*state.counter
},
more20stu(state){
return state.students.filter(s=>{
return s.age>20
})
},
more20stuLength(state,getters){
return getters.more20stu.length;
},
moreAgestu(state){
return function(age){
return state.students.filter(s=>s.age>age)
}
}
},
modules:{
}
})
export default store
App.vue
<template>
<div id="app">
<!-- <h2>{{message}}</h2> -->
<h1>app={{$store.state.counter}}</h1>
<button @click="addtion">+</button>
<button @click="subtraction">-</button>
<h2>-------getter-----------</h2>
<h1>{{$store.getters.powerCounter}}</h1>
<h1>more20stu={{$store.getters.more20stu}}</h1>
<h1>more20stuLength={{$store.getters.more20stuLength}}</h1>
<h1>moreAgestu(10)={{$store.getters.moreAgestu(10)}}</h1>
<hello-vuex />
</div>
</template>
<script>
import HelloVuex from "./components/HelloVuex.vue"
export default {
name: 'App',
data(){
return{
message:'我是App组件',
}
},
computed: {
more20stu(){
return this.$store.state.students.filter(s=>{
return s.age>=20
})
}
},
methods:{
addtion(){
this.$store.commit('increment')
},
subtraction(){
this.$store.commit('decrement')
}
},
components: {
HelloVuex
}
}
</script>
<style>
</style>
Mutation
Vuex的store状态的更新唯一方式:提交Mutation
Mutation主要包括两部分:
字符串的事件类型(type)
一个回调函数(handler),该回调函数的第一个参数就是state。
通过mutation更新
Mutation传递参数
store->index.js
mutations:{
//方法
increment(state){
state.counter++
},
decrement(state){
state.counter--
},
incrementCount(state,count){
//state.counter+=count
console.log(count)
state.counter+=count.count
},
addStudent(state,stu){
state.students.push(stu)
}
}
App.vue
methods:{
addtion(){
this.$store.commit('increment')
},
subtraction(){
this.$store.commit('decrement')
},
addCount(count){
// this.$store.commit('incrementCount',count)
this.$store.commit({
type:'incrementCount',
count
})
// console.log(count)
},
addStudent(){
const stu={id:105,name:'强强',age:22}
this.$store.commit('addStudent',stu)
}
}
属性被加入到响应式系统中,响应式系统会监听属性的变化。
Mutation响应规则
Vuex的store中的state是响应式的, 当state中的数据发生改变时, Vue组件会自动更新.
Vue.set(state.info,'address','四川')
Vue.delete(state.info,'age')
Mutation常量类型 – 代码
actions
index.js
actions:{
aupdateInfo(context,payload){
// setTimeout(() => {
// context.commit('updateInfo')
// // console.log(payload)
// // payload()
// console.log(payload.message)
// payload.success();
// }, 1000);
return new Promise((resolve,reject)=>{
setTimeout(() => {
context.commit('updateInfo')
console.log(payload)
resolve('11111')
}, 1000);
})
}
},
App.vue
updateInfo(){
//this.$store.commit('updateStudent')
//this.$store.dispatch('aupdateInfo','我是payload')
// this.$store.dispatch('aupdateInfo',()=>{
// console.log('里面已经完成了')
// })
// this.$store.dispatch('aupdateInfo',{
// message:'我是携带的信息',
// success:()=>{
// console.log('我成功了')
// }
// })
this.$store
.dispatch('aupdateInfo','我是携带的信息')
.then(res=>{
console.log('里面完成了回调')
console.log(res)
})
}
认识Module
Vuex允许我们将store分割成模块(Module), 而每个模块拥有自己的state、mutations、actions、getters等
App.vue
<template>
<div id="app">
<h2>------module-----</h2>
<h2>{{$store.state.a.name}}</h2>
<button @click="updateName">修改模块里的名字</button>
<h2>module的getter的fullname={{$store.getters.fullname}}</h2>
<h2>module的getter的fullname2={{$store.getters.fullname2}}</h2>
<h2>module的getter的fullname3={{$store.getters.fullname3}}</h2>
<button @click="asyncUpdateName">异步修改名字</button>
<h1>app={{$store.state.counter}}</h1>
<button @click="addtion">+</button>
<button @click="subtraction">-</button>
<button @click="addCount(5)">+5</button>
<button @click="addCount(10)">+10</button>
<button @click="addStudent">添加学生</button>
<h2>------响应式修改-----</h2>
<h2>info={{$store.state.info}}</h2>
<button @click="updateInfo">修改info信息</button>
<h2>-------getter-----------</h2>
<h1>{{$store.getters.powerCounter}}</h1>
<h1>more20stu={{$store.getters.more20stu}}</h1>
<h1>more20stuLength={{$store.getters.more20stuLength}}</h1>
<h1>moreAgestu(10)={{$store.getters.moreAgestu(10)}}</h1>
<hello-vuex />
</div>
</template>
<script>
import HelloVuex from "./components/HelloVuex.vue"
export default {
name: 'App',
data(){
return{
message:'我是App组件',
}
},
computed: {
more20stu(){
return this.$store.state.students.filter(s=>{
return s.age>=20
})
}
},
methods:{
asyncUpdateName(){
this.$store.dispatch('aupdateName')
},
updateName(){
this.$store.commit('updateName','李四')
},
addtion(){
this.$store.commit('increment')
},
subtraction(){
this.$store.commit('decrement')
},
addCount(count){
// this.$store.commit('incrementCount',count)
this.$store.commit({
type:'incrementCount',
count
})
// console.log(count)
},
addStudent(){
const stu={id:105,name:'强强',age:22}
this.$store.commit('addStudent',stu)
},
updateInfo(){
//this.$store.commit('updateStudent')
//this.$store.dispatch('aupdateInfo','我是payload')
// this.$store.dispatch('aupdateInfo',()=>{
// console.log('里面已经完成了')
// })
// this.$store.dispatch('aupdateInfo',{
// message:'我是携带的信息',
// success:()=>{
// console.log('我成功了')
// }
// })
this.$store
.dispatch('aupdateInfo','我是携带的信息')
.then(res=>{
console.log('里面完成了回调')
console.log(res)
})
}
// updateStudent(state,payload){
// this.$store.commit('updateStudent',{height:1.62})
// }
},
components: {
HelloVuex
}
}
</script>
<style>
</style>
index.js
context只在自己的内部找
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const moduleA={
state:{
name:'琪琪'
},
mutations:{
updateName(state,payload){
state.name=payload
}
},
actions:{
aupdateName(context){
setTimeout(() => {
console.log(context)
context.commit('updateName','雪花')
}, 1000);
}
},
getters:{
fullname(state){
return state.name+'1111'
},
fullname2(state,getters){
return getters.fullname+'2222'
},
fullname3(state,getters,rootState){
return getters.fullname2+rootState.counter
}
}
}
const store=new Vuex.Store({
state:{
counter:1000,
students:[
{id:100,name:"苹苹",age:21},
{id:101,name:"晴晴",age:11},
{id:102,name:"金金",age:21},
{id:103,name:"憨憨",age:1}
],
info:{
name:'小苹苹',
age:21,
hobby:'美食'
}
},
mutations:{
//方法
increment(state){
state.counter++
},
decrement(state){
state.counter--
},
incrementCount(state,count){
//state.counter+=count
console.log(count)
state.counter+=count.count
},
addStudent(state,stu){
state.students.push(stu)
},
updateInfo(state){
state.info.name="小强强"
// Vue.set(state.info,'address','四川')
// Vue.delete(state.info,'age')
}
// updateStudent(state,payload){
// // state.info.name="小强强"
// // Vue.set(state.info,'address','四川')
// // Vue.delete(state.info,'age')
// //方式一:Vue.set()
// //Vue.set(state.info,'height',payload.height)
// //方式二
// state.info={...state.info,'height':payload.height}
// }
},
actions:{
aupdateInfo(context,payload){
// setTimeout(() => {
// context.commit('updateInfo')
// // console.log(payload)
// // payload()
// console.log(payload.message)
// payload.success();
// }, 1000);
return new Promise((resolve,reject)=>{
setTimeout(() => {
context.commit('updateInfo')
console.log(payload)
resolve('11111')
}, 1000);
})
}
},
getters:{
powerCounter(state){
return state.counter*state.counter
},
more20stu(state){
return state.students.filter(s=>{
return s.age>=20
})
},
more20stuLength(state,getters){
return getters.more20stu.length;
},
moreAgestu(state){
return function(age){
return state.students.filter(s=>s.age>age)
}
}
},
modules:{
a:moduleA
}
})
export default store
项目结构
当我们的Vuex帮助我们管理过多的内容时, 好的项目结构可以让我们的代码更加清晰.