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>
<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++
}
}