一、Vuex是什么?
Vuex是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化,方便的实现组件之间数据的共享。
简单地说:如果不使用vuex,那么传递数据可能需要经过链式一级一级的传递,而用了vuex则可以直接传递数据。
使用Vuex的好处
- 能够在vuex中集中管理共享的数据,易于开发和后期维护。
- 能够高效地实现组件之间的数据共享,提高开发效率。
- 存储在vuex中的数据都是响应式的,能够试试保持数据与页面同步。
二、知识要点
State
State提供唯一的公共数据源,所有共享数据都要统一放到Store的State中进行存储。
//创建store数据源,提供唯一公共数据
const store = new Vuex.Store({
state: {
····
}
})
组件访问state中数据的第一种方式
this.$store.state.全局数据名称
组件访问数据的第二种方式:使用mapstate函数。
//先导入mapstate函数
import {mapState} from 'vuex';
computed: {
// 通过mapstate函数,将当前组件要的全局教程映射为当前组件的computed。
// ES6中的展开运算符
...mapState(['count'])
},
Mutaion
mutaion用于变更Store中的数据
特点:
- 只能通过mutaion变更Store数据,不可以直接操作Store中的数据。
- 通过这种方式虽然操作起来稍微繁琐一些,但是可以集中监控所有数据变化。
声明mutations函数
mutations{
函数名1(state){
···
},
//带参数
函数名(state, 参数名){
···
}
}
触发mutations的第一种方法
methods: {
函数名(){
// commit的作用就是调用某个mutation函数
this.$store.commit('mutations函数名');
},
//触发带参数mutations函数
函数名(){
this.$store.commit('mutations函数名', 参数值);
}
}
触发mutations的第二种方法
先导入mapMutations函数。
import {mapMutations} from 'vuex';
再将指定的mutations函数,映射为当前组件的methods函数
methods: {
...mapMutations(['mutations函数名']),
函数名(){
this.mutations函数名();
},
//触发带参数的mutations函数
函数名(){
this.mutations函数名(参数);
}
}
注意:不能在mutations函数中执行写异步的操作。actions用于处理异步任务。
Actions
如果通过异步操作变更数据,必须通过Actions,而不能使用mutations,但是在Actions中还是要通过触发mutations函数的方式简介变更数据。
声明mutations函数
actions: {
函数名(context) {
···异步操作代码
},
//带参数
函数名(context, 参数名) {
···异步操作代码
}
}
触发Actions函数的第一种方式
methods: {
函数名(){
this.$store.dispatch('Action函数名');
}
函数名(){
this.$store.dispatch('Action函数名', 参数名);
}
}
触发Actions函数的第二种方式
先导入mapActions函数
import {mapActions} from 'vuex'
再将指定的Actions函数,映射为当前组件的methods函数
methods: {
...mapActions(['Actions函数名, Actions函数名'])
函数名(){
this.Actions函数名();
},
//带参数
函数名(){
this.Actions函数名(参数);
}
}
Getters
Getter用于对Store中的数据进行加工处理形成新的数据。
特点
- Getter可以对Store中已有的数据加工处理后形成新的数据,类似Vue中的计算属性
- Store中数据发生变化,Getter中的数据也会跟着变化
getters: {
包装的新数据名(state) {
···
return ····
}
}
第一种使用方法
this.$store.getters.名称
第二种使用方法
先导入mapActions函数
import {mapGetters} from 'vuex'
用mapGetters方法映射为当前组件的computed计算属性
computed: {
...mapGetters(['getters包装的新数据名'])
}
三、小案例:ToDoList
效果展示
这里用的Vue CLI搭建的项目
局部安装vuex
cnpm install vuex --save
本案例依赖Ant Design插件,局部安装Ant Design(cnpm比npm更快)
cnpm i ant-design-vue --save
src/main.js
import Vue from 'vue'
import App from './vuex.vue'//导入根组件
import Antd from 'ant-design-vue';
import 'ant-design-vue/dist/antd.css';
import store from './store'
Vue.config.productionTip = false
Vue.use(Antd);
new Vue({
store,
render: h => h(App)//vue新写法
}).$mount('#app')
public/list.json
[{
"id": 0,
"info": "Racing car sprays burning fuel into crowd.",
"done": true
},
{
"id": 1,
"info": "Japanese princess to wed commoner.",
"done": false
},
{
"id": 2,
"info": "Australian walks 100km after outback crash.",
"done": true
},
{
"id": 3,
"info": "Man charged over missing wedding girl.",
"done": false
},
{
"id": 4,
"info": "Los Angeles battles huge wildfires.",
"done": false
}
]
vuex.vue
<template>
<div id="app">
<a-input placeholder="请输入任务" class="my_ipt" />
<a-button type="primary">添加事项</a-button>
<a-list bordered :dataSource="list" class="dt_list">
<a-list-item slot="renderItem" slot-scope="item">
<!-- 复选框 -->
<a-checkbox>{{ item.info }}</a-checkbox>
<!-- 删除链接 -->
<a slot="actions">删除</a>
</a-list-item>
<!-- footer区域 -->
<div class="footer" slot="footer">
<span>0条剩余</span>
<a-button-group>
<a-button type="primary">全部</a-button>
<a-button>未完成</a-button>
<a-button>已完成</a-button>
</a-button-group>
<a>清除已完成</a>
</div>
</a-list>
</div>
</template>
<script>
export default {
name: "app",
data() {
return {
list: [
{
id: 0,
info: "Racing car sprays burning fuel into crowd.",
done: false,
},
{
id: 1,
info: " Japanese princess to wed commoner.",
done: false,
},
{
id: 2,
info: "Australian walks 100km after outback crash.",
done: false,
},
{
id: 3,
info: "Man charged over missing wedding girl.",
done: false,
},
{
id: 4,
info: "Los Angeles battles huge wildfires.",
done: false,
},
],
};
},
};
</script>
<style scoped>
#app {
padding: 10px;
}
.my_ipt {
width: 500px;
margin-right: 10px;
}
.dt_list {
width: 500px;
margin-top: 10px;
}
.footer {
display: flex;
justify-content: space-between;
align-items: center;
}
</style>
store/index.vue
import Vue from 'vue'
import Vuex from 'vuex'
import axios from 'axios'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
// 所有的任务列表
list: [],
// 文本框的内容
inputValue: 'aaa',
// 下一个Id
nextId: 5,
viewKey: 'all'
},
mutations: {
initList(state, list) {
state.list = list
},
// 为 store 中的 inputValue 赋值
setInputValue(state, val) {
state.inputValue = val
},
// 添加列表项
addItem(state) {
const obj = {
id: state.nextId,
info: state.inputValue.trim(),
done: false
}
state.list.push(obj)
state.nextId++
state.inputValue = ''
},
// 根据Id删除对应的任务事项
removeItem(state, id) {
// 根据Id查找对应项的索引
const i = state.list.findIndex(x => x.id === id)
// 根据索引,删除对应的元素
if (i !== -1) {
state.list.splice(i, 1)
}
},
// 修改列表项的选中状态
changeStatus(state, param) {
const i = state.list.findIndex(x => x.id === param.id)
if (i !== -1) {
state.list[i].done = param.status
}
},
// 清除已完成的任务
cleanDone(state) {
state.list = state.list.filter(x => x.done === false)
},
// 修改视图的关键字
changeViewKey(state, key) {
state.viewKey = key
}
},
actions: {
getList(context) {
axios.get('/list.json').then(({ data }) => {
// console.log(data)
context.commit('initList', data)
})
}
},
getters: {
// 统计未完成的任务的条数
unDoneLength(state) {
return state.list.filter(x => x.done === false).length
},
infolist(state) {
if (state.viewKey === 'all') {
return state.list
}
if (state.viewKey === 'undone') {
return state.list.filter(x => !x.done)
}
if (state.viewKey === 'done') {
return state.list.filter(x => x.done)
}
return state.list
}
}
})
我是孤城浪人,一名正在前端路上摸爬滚打的菜鸟,欢迎你的关注。