vue_vuex学习
vuex结构
- src/store/index.js
import Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex) export default new Vuex.Store({ state: { }, mutations: { }, actions: { }, modules: { }, getter: { } })
state
: state中保存了数据,可以放在各个组件中的数据,组件想要获取到数据,有两种方式mutation
: mutation只做纯粹的state数据修改操作,mutation需要被提交(commit)才能执行action
: action可以进行异步请求,将数据commit给mutation。action中还可以进行数据处理,将数据处理成mutation可以直接使用的数据modules
: store的子模块,为了开发大型项目,方便状态管理而使用的getters
: 对state属性进行计算,可以理解类似于Vue中computed
引入vuex
import store from './store'
new Vue({
router,
store,
render: h => h(App)
}).$mount('#app')
vuex的使用
state
src/store/index.js
export default new Vuex.Store({
state: {
counter: 10
}
})
App.vue
<template>
<div id="app">
<div>{{$store.state.counter}}</div>
<div>
</template>
mutation
src/store/index.js
export default new Vuex.Store({
state: {
counter: 10,
},
mutations: {
addCounter(state) {
state.counter++
},
addCountNum(state, num) {
state.counter += num
},
addStudent(state, stu) {
state.student.push(stu)
}
}
})
App.vue
<template>
<div id="app">
<div>{{$store.state.counter}}</div>
<div @click="add">+</div>
<button @click="addNum(10)">10+</button>
<button @click="addStudent">stu+</button>
</div>
</template>
<script>
export default {
name: 'App',
components: {
},
methods: {
add(){
this.$store.commit('addCounter')
},
addNum(num) { //传参提交
this.$store.commit('addCountNum', num)
},
addStudent() { //传参提交(参数为对象)
let stu = {name: 'test', age: 50};
this.$store.commit('addStudent', stu)
}
}
}
</script>
- mutation添加和删除state
<template>
<div id="app">
<div>{{$store.state.info}}</div>
</template>
<script>
export default {
name: 'App',
components: {
},
methods: {
updata(){
this.$store.commit('updataIn')
}
}
}
</script>
export default new Vuex.Store({
state: {
info: {
age: 12,
name: 'xxx'
}
},
mutations: {
updataIn(state) {
//使用set增加state,第一个属性为修改的对象,第二个属性为key/index,第三个属性为值
// Vue.set(state.info,'address','ShangHai')
//使用delete删除state,第一个属性为修改的对象,第二个属性为key/index
// Vue.delete(state.info,'age')
}
}
})
- mutation的提交风格
- 这种方式在store中接收到的为num的值
-
//vue中的method提交 this.$store.commit('addCountNum', num) //store接收 addCountNum(state, num) { state.counter += num }
- 这种方式在store中接收到的为对象
-
//vue中的method提交 this.$store.commit( type:'addCountNum', num ) //store接收 addCountNum(state, num) { //此时的num为一个对象,而传来的num为对象里的属性,num可写为payload state.counter += num.num }
action
- 通常情况下
mutation
的方法必须是同步方法,主要是devtools
不能捕捉到mutation
的异步操作会什么时候完成 action
类似于mutation
,但是是用来替代mutation
完成异步操作的- 常规使用
src/store/index.js
export default new Vuex.Store({ state: { info: { age: 12, name: 'xxx' } }, mutations: { updataIn(state) { state.info.name = 'test' } }, actions: { //context:上下文 updataInfo(context,payload){ setTimeout(() => { context.commit('updataIn') console.log(payload.message) payload.success() },1000) } })
App.vue
<template> <div id="app"> <div>{{$store.state.info}}</div> <button @click="updata">updata</button> </div> </template> <script> export default { name: 'App', components: { }, methods: { updata(){ this.$store.dispatch( 'updataInfo', { message: '传递的信息', success: () => { console.log('传递成功') } } ) } } } </script>
- 结合Promise使用
src/store/index.js
export default new Vuex.Store({ state: { info: { age: 12, name: 'xxx' } }, mutations: { updataIn(state) { state.info.name = 'test' } }, actions: { //context:上下文 updataInfo(context,payload){ return new Promise((resolve, reject) => { setTimeout(() => { context.commit('updataIn') console.log(payload.message) payload.success() resolve('111') },1000) }) } } })
App.vue
<template> <div id="app"> <div>{{$store.state.info}}</div> <button @click="updata">updata</button> </div> </template> <script> export default { name: 'App', components: { }, methods: { updata(){ this.$store.dispatch( 'updataInfo', { message: '传递的信息', success: () => { console.log('传递成功') } } ).then(res => { console.log(res) }) } } } </script>
modules
src/store/index.js
const moduleA ={
state: {
name: '2020/08/07'
},
mutations: {
updata(state) {
state.name = '08/07'
}
},
action: {},
getters:{
updataName(state) {
return state.name + '/00'
},
fullname(state, getters, rootState) {
return getters.updataName + rootState.counter
}
}
}
export default new Vuex.Store({
modules: {
a: moduleA
}
})
App.vue
<template>
<div id="app">
<div>{{$store.state.a.name}}</div>
<div>{{$store.getters.updataName}}</div>
<div>{{$store.getters.fullname}}</div>
<button @click="updataName">updataName+</button>
</div>
</template>
<script>
export default {
name: 'App',
components: {
},
methods: {
updataName() {
this.$store.commit('updata')
}
}
}
</script>
- 使用modules中的
state
时,$store
后需接上定义的模块名 - 使用modules中的
mutations
时,与之前相同,commit
里的type类型是统一的,首先会搜先store
,之后再搜索其他模块,所以mutations
之间最好不要同名 - 使用modules中的
action
时,与之前相同,dispatch
里的type类型是统一的,首先会搜先store
,之后再搜索其他模块,所以action
之间最好不要同名 - 使用modules中的
getters
时,与之前相同,所以getters
之间最好不要同名 modules
内可使用rootState
参数来获取store
里state
的数据,可使用rootGetters
参数来获取store
里getters
的数据,其他可直接调用
getters
src/store/index.js
export default new Vuex.Store({
state: {
counter: 10,
student: [
{name: 'joe', age: 21},
{name: 'jack', age: 15},
{name: 'curry', age: 40}
]
},
getters: {
//处理state里的值并返回
powerCounter(state){
return state.counter * state.counter
},
//处理并筛选state里的对象并返回
more20stu(state) {
return state.student.filter(item => {
return item.age >= 20
})
},
// 引用其他getters方法获取处理值
more20stuLen(state, getters) {
return getters.more20stu.length
},
//实现动态传参
moreAgestu(state){
return age => {
return state.student.filter(item => {
return item.age >= age
})
}
}
}
})
App.vue
<template>
<div id="app">
<div>{{$store.state.counter}}</div>
<div>{{$store.getters.powerCounter}}</div>
<div>{{$store.getters.more20stu}}</div>
<div>{{$store.getters.more20stuLen}}</div>
<div>{{$store.getters.moreAgestu(30)}}</div>
</div>
</template>
对象解构
- 这种方式可以将
context
内的值赋值给相应的参数 -
const context = { state; 'xxx', commit: 'yyy', rootState: 'zzz' } const {state, commit, rootState} = context
- 这样操作所得:
state = context.state,commit = context.commit,rootState = context.rootState
modules
中的实例const moduleA ={ state: { name: '2020/08/07' }, mutations: { updata(state) { state.name = '08/07' } }, action: { //对象解构 test ({state, commit, rootState}) { console.log(state.name); commit('updata'); console.log(rootState.counter); } } }
vuex模块封装
如果项目过大的话代码仅仅放在index.js文件中会显得代码十分拥挤且不利于维护,所以我们可以将模块抽离出来,以下是抽离的文件目录:
index.js
import Vue from 'vue'
import Vuex from 'vuex'
import mutations from "@/store/mutations";
import actions from "@/store/actions";
import moduleA from "@/store/modules/moduleA";
import getters from "@/store/getters";
Vue.use(Vuex)
const state = {
counter: 10,
student: [
{name: 'joe', age: 21},
{name: 'jack', age: 15},
{name: 'curry', age: 40}
],
info: {
age: 12,
name: 'xxx'
}
}
export default new Vuex.Store({
state,
mutations,
actions,
modules: {
a: moduleA
},
getters
})
motations.js
(其他文件也与此文件相同)
export default {
addCounter(state) {
state.counter++
}
}