vuex
注意: 子孙组件之间建议用 provide/inject(后续更新),不要滥用Vuex;
什么时候用vuex?
- 当一个组件需要多次派发事件
- 跨组件共享数据、跨页面共享数据
vuex使用
在安装vuex之后,在项目中会多出一个store目录,目录下有一个index.js文件
Vue.use(Vuex);
const store = new Vuex.Store({
// 在开发环境开启严格模式 这样修改数据 就必须通过 mutation 来处理
strict: products.env.NODE_ENV !== "production",
//状态 相当于data里面的数据
state: {
name: "卜卜",
age: 21,
},
//用来处理状态
mutations: {},
//用于异步处理
actions: {},
//用来挂载模块
modules: {
app,
settings,
user,
},
// getters,
});
export default store;
在mian.js将store挂载到Vue中,便于全局使用
Vue.config.productionTip = false
new Vue({
el: '#app',
router,
store,
render: h => h(App)
})
1.state
state里面的数据类似于data里面的初始值
Vue.use(Vuex);
const store = new Vuex.Store({
// 在开发环境开启严格模式 这样修改数据 就必须通过 mutation 来处理
strict: products.env.NODE_ENV !== "production",
//状态 相当于data里面的数据
state: {
name: "卜卜",
age: 21,
},
mutations: {},
actions: {},
modules: {
app,
settings,
user,
},
});
export default store;
2.组件获取state里数据的方法
通过 this.$store.state.[属性] (this可以省略)
<template>
<div class="dashboard-container">
<div class="dashboard-form">{{ this.$store.state.name }}</div>
</div>
</template>
通过 mapState
<template>
<div class="dashboard-container">
<div>{{ name }}</div>
<div>{{ age }}</div>
</div>
</template>
<script>
import { mapState } from "vuex";
export default {
name: "Dashboard",
data() {
return {};
},
computed: {
...mapState(["name", "age"]),
},
};
</script>
mapState还可以在对象中给状态起别名,在 mapState 方法里传递一个对象而不是数组
<template>
<div class="dashboard-container">
<div >{{ name1 }}</div>
<div>{{ name2 }}</div>
</div>
</template>
<script>
import { mapState } from "vuex";
export default {
name: "Dashboard",
data() {
return {};
},
computed: {
...mapState({ name1: "name", name2: "age" }),
},
};
</script>
2.mutations
Store 中的状态不能直接对其进行操作,我们得使用 Mutation 来对 Store 中的状态进行修改
在组件中使用mutation的方法
1、使用
this.$store.commit()里面的第一个参数是state - Store 中的状态(必须传递)
后面多个是传入的参数
<template>
<div class="dashboard-container">
<div>{{ name }}</div>
<div>{{ age }}</div>
<button @click="btnChangeAge">切换</button>
</div>
</template>
<script>
import { mapGetters, mapState } from "vuex";
export default {
data() {
return {};
},
computed: {
...mapState(["name", "age"]),
},
created() {},
methods: {
btnChangeAge() {
//例如这里调用
this.$store.commit("changeAge", "18");
},
},
};
</script>
2、 使用
mapMutations例如切换年龄为55
<template>
<div>
<p>{{ this.$store.state.age }}</p>
<button @click="changeAge(55)">点击切换年纪</button>
</div>
</template>
<script>
import { mapMutations} from "vuex";
export default {
data() {
return {};
},
computed: {},
methods: {
...mapMutations(["changeAge"]),
},
};
</script>
3、actions
action用来处理异步任务,通过action触发mutations间接改变状态,不能直接通过mutations直接改变异步状态
Action 类似于 mutation,不同在于:
- Action 提交的是 mutation,而不是直接变更状态。
- Action 可以包含任意异步操作。
actions中调用方法的参数,第一个是上下文默认传递的参数,第二个是自己传递的参数
const store = new Vuex.Store({
state: {
name: "卜卜",
age: 21
},
mutations: {
changeAge(state, ageValue) {
state.age = ageValue;
}
},
//用于异步处理
actions: {
//使用setTimeout模拟异步
changeAgeSet(content, ageValue) {
setTimeout(() => {
//调用mutations中的方法
content.commit("changeAge", ageValue);
}, 3000);
}
},
//用来挂载模块
modules: {}
});
在组件中使用actions的方法
1、使用
this.$store.dispatch(mutations中的方法名,传入的参数)
<template>
<div>
<p>{{ this.$store.state.age }}</p>
<button @click="changeAgeItem(66)">actions切换年纪</button>
</div>
</template>
<script>
import { mapMutations, mapState } from "vuex";
export default {
data() {
return {};
},
computed: {
...mapState(["name", "age"]),
},
methods: {
changeAgeItem(ageValue) {
//调用actions中的方法
this.$store.dispatch("changeAgeSet", ageValue);
},
},
};
</script>
2、使用
mapActions例如改变年龄为66
<template>
<div>
<p>{{ this.$store.state.age }}</p>
<button @click="changeAgeSet(66)">actions切换年纪</button>
</div>
</template>
<script>
//这里注意引入mapActions
import { mapActions, mapMutations, mapState } from "vuex";
export default {
data() {
return {};
},
computed: {
...mapState(["name", "age"]),
},
methods: {
//通过mapActions调用actions中的方法
...mapActions(["changeAgeSet"]),
},
};
</script>
4、getters
store 中定义“getter”(可以认为是 store 的计算属性)
const store = new Vuex.Store({
state: {
name: "卜卜",
age: 21
},
mutations: {
changeAge(state, ageValue) {
state.age = ageValue;
}
},
//用于异步处理
actions: {
//使用setTimeout模拟异步
changeAgeSet(content, ageValue) {
setTimeout(() => {
//调用mutations中的方法
content.commit("changeAge", ageValue);
}, 3000);
}
},
//用来挂载模块
modules: {},
getters: {
descriptAge(state) {
return `my age is ${state.age}`;
}
}
});
调用getter的方法
1、
this.$store.getters.方法名
<div>
<button @click="changeAgeSet(66)">actions切换年纪</button>
<p>{{ this.$store.getters.descriptAge }}</p>
</div>
2、
mapGettersmapGetters辅助函数仅仅是将 store 中的 getter 映射到局部计算属性:
<template>
<div>
<p>{{ descriptAge }}</p>
</div>
</template>
<script>
import { mapGetters } from "vuex";
export default {
data() {
return {};
},
computed: {
//使用mapGetters
...mapGetters(["descriptAge"]),
},
};
如果你想将一个 getter 属性另取一个名字,使用对象形式:
computed: {
//使用对象形式
...mapGetters({ newAge: "descriptAge" }),
},
5、Modules
由于使用单一状态树,应用的所有状态会集中到一个比较大的对象。当应用变得非常复杂时,store 对象就有可能变得相当臃肿。
为了解决以上问题,Vuex 允许我们将 store 分割成模块(module) 。每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块——从上至下进行同样方式的分割
module的使用
1、在vuex文件夹下创建一个modules文件夹在modules底下新增example.js文件,在example.js里面写入 state、mutations、actions
const state = {
age: 100
};
const mutations = {
changeAge(state, ageValue) {
state.age = ageValue;
}
};
//导出
export default {
state,
mutations
};
2、在vuex/index.js中的 modules 进行挂载这个模块
import Vue from "vue";
import Vuex from "vuex";
//引入example.js
import example from "./modules/example";
Vue.use(Vuex);
const store = new Vuex.Store({
//用来挂载模块
modules: {
example
},
})
export default store;
3、在组件中的使用
1、通过this.$store.state[在module中挂载的模块名][挂载的模块里的属性]
<template>
<div>
<p>{{ this.$store.state.example.age }}</p>
</div>
</template>
2、也可以通过mapXXX的形式进行映射
先在导出里添加命名空间namespaced: true
const state = {
age: 100
};
const mutations = {
changeAge(state, ageValue) {
state.age = ageValue;
}
};
export default {
//添加命名空间
namespaced: true,
state,
mutations
};
在组件中使用:
<template>
<div>
<p>{{ age }}</p>
</div>
</template>
<script>
import { mapActions, mapGetters, mapMutations, mapState } from "vuex";
export default {
data() {
return {};
},
computed: {
//在组件中使用
...mapState("example", ["age"]),
},
};
</script>