本文将从Vuex的核心概念出发,通过讲解一个待办清单的小项目,帮助大家更好的理解Vuex。此文主要是根据近日学习的关于Vuex的内容,整理出的学习笔记,用来巩固与记录。欢迎大家交流与讨论!
主要参考视频为黑马程序员的“Vue全家桶-Vuex” 原视频地址
https://www.bilibili.com/video/BV1h7411N7bg?from=search&seid=5930582975536399924&spm_id_from=333.337.0.0
若有侵权,请邮箱联系[email protected] 联系,我会及时删除。敬礼!
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式 +
库。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
参考教程:https://vuex.vuejs.org/zh/
那么什么是状态管理模式呢?在一般情况下,我们的vue应用在渲染数据时,是一个单项数据流的过程,驱动的数据源为状态,状态会以声明方式映射到视图,用户通过在视图上操作又会导致状态变化。如图所示:
我们多个视图依赖同一状态(数据)、或不同的视图需要变更同一状态(数据)时,若没有一个统一的状态管理器,但是又需要实现数据共享时,过程就会变得麻烦。按照传统方式,我们是可以通过各个组件传参来达成数据共享,但若项目变大,传参的过程就会变得相当繁琐,且后期维护的成本也很高。
所以Vuex作为一个状态管理器,可以把不同组件的共享状态抽离出来,集中管理便于后期维护,并利用vuex的响应式的特点从而实现高效进行状态更新。
在安装好vuex之后,将出现store文件夹,里面有index.js的文件,代码如下:
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
},
mutations: {
},
actions: {
},
modules: {
}
})
下面将一一介绍Store的核心。
State为Vuex的公共状态,提供唯一的数据源,用来存储公共的数据。
代码如下:
state: {
// 所有的任务列表
list: [],
},
当我们要访问存放在State里面的数据可通过以下两种方式:
this.$stroe.state.全局数据名称
//1. 从vuex中按需导入 mapState 函数
import { mapState } from 'vuex'
//2. 通过 mapState 函数,将当前组件需要的全局数据映射为当前组件
computed: {
...mapState(['list']),
},
Mutations用于变更Store中的数据。
假设要实现一个点击自增的功能,首先需要在Store中定义Mutations代码如下:
export default new Vuex.Store({
state: {
count: 0
},
mutations: {
//加1
add(state){
//变更状态
state.count++
}
//携带参数,加n
addN(state,n){
//变更状态
state.count += n
}
},
})
触发mutations需通过以下两种方式:
methods: {
handle() {
this.$store.commit('add')
}
}
//携带参数
methods: {
handle1() {
this.$store.commit('addN',n)
}
}
//1. 从vuex中按需导入 mapMutations 函数
import { mapMutations } from 'vuex'
//2. 将指定的 mutations 函数,映射为当前组件的methods方法
methods: {
...mapMutations(['add']),
handle(){
this.add()
},
//携带参数
handle1(){
this.addN(5)
}
},
Actions用于处理异步任务
假设要实现一个延时添加的功能,在Store中定义actions代码如下:
export default new Vuex.Store({
state: {
count: 0
},
mutations: {
add(state){
//变更状态
state.count++
}
},
actions: {
addAsync(context) {
//异步动作,如延时添加
setTimeout(() => {
context.commit('add')
}, 1000)
}
},
})
触发actions可通过以下两种方式:
methods: {
handle() {
this.$store.dispatch('addAsync')
}
}
//1. 从vuex中按需导入 mapActions 函数
import { mapAction } from 'vuex'
//2. 将指定的 mutations 函数,映射为当前组件的methods方法
methods: {
...mapActions(['addAsync']),
},
Getters用于对Store中的数据进行加工处理形成新的数据。
在Store中定义Getter代码如下:
export default new Vuex.Store({
state: {
count: 0
},
getters: {
showNum(state) {
return '当前最新的数量是【' + state.count + '】'
},
}
},
})
使用getters可通过以下两种方式:
this.$store.getters.名称
//1. 从vuex中按需导入 mapActions 函数
import { mapGetters } from 'vuex'
//2. 将指定的 mutations 函数,映射为当前组件的methods方法
computed: {
...mapGetters(['showNum']),
},
(携带参数)
源码:https://gitee.com/wx_f6a2d8acc5/vuex-to-do-list.git
我们的待办清单基本布局与功能点如上图所示
html代码如下:
<template>
<div id="app">
<a-input
placeholder="请输入任务"
class="my_ipt"
:value="inputValue"
@change="handleInputChange"
/>
<a-button type="primary" @click="addItemToList">添加事项a-button>
<a-list bordered :dataSource="list" class="dt_list">
<a-list-item slot="renderItem" slot-scope="item">
<a-checkbox
:checked="item.done"
@change="cbStatusChanged($event, item.id)"
>{{ item.info }}a-checkbox
>
<a slot="actions" @click="removeItemById(item.id)">删除a>
a-list-item>
<div class="footer" slot="footer">
<span>{{ unDoneLength }}条剩余span>
<a-button-group>
<a-button
:type="viewKey === 'all' ? 'primary' : 'default'"
@click="changeList('all')"
>全部a-button
>
<a-button
:type="viewKey === 'undone' ? 'primary' : 'default'"
@click="changeList('undone')"
>未完成a-button
>
<a-button
:type="viewKey === 'done' ? 'primary' : 'default'"
@click="changeList('done')"
>已完成a-button
>
a-button-group>
<a @click="clean">清除已完成a>
div>
a-list>
div>
template>
下面将按功能点分别介绍实现思路
前端模拟数据可把list列表数据单独存放在一个json文件里,利用axios获取
字段释义:
id
待办清单项idinfo
待办清单项内容done
是否已完成(true
为已完成,false
为未完成)list.json 代码如下:
[
{
"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": true
},
{
"id": 3,
"info": "Man charged over missing wedding girl.",
"done": false
},
{
"id": 4,
"info": "Los Angeles bat∏tles huge wildfires.",
"done": false
}
]
在store/index.js 中,首先在state中定义数据
state: {
// 所有的任务列表
list: [],
},
在页面初始化时获取数据
created() {
// 1、App.vue 页面初始化时调用vuex中的action 异步获取数据
this.$store.dispatch('getList')
},
Actions异步获取本地数据
actions: {
// 2、在action中 异步获取数据,并把数据提交给mutations中initList函数处理梳理
getList(context) {
axios.get('/list.json').then(({ data }) => {
console.log(data)
context.commit('initList', data)
})
},
addAsync(context) {
// 异步动作,如延时添加
setTimeout(() => {
context.commit('add')
}, 1000)
}
},
Actions在mutation中对state数据进行赋值
mutations: {
// 3、在mutation中对state数据进行赋值
initList(state, list) {
state.list = list
},
App.vue 中Actions在mutation中对state数据进行赋值
// 4、使用store的计算属性,把store中存储的数据映射过来
computed: {
...mapState(['list']),
},
实现思路:
App.vue 代码如下:
methods: {
// 监听文本
handleInputChange(e) {
console.log(e.target.value)
this.$store.commit('setInputValue', e.target.value)
},
// 向列表中增加Item项
addItemToList() {
if (this.inputValue.trim().length <= 0) {
return this.$message.warning('输入内容不能为空')
} else {
this.$store.commit('addItem')
}
},
store/index.js 代码如下:
state: {
// 所有的任务列表
list: [],
// 文本框内容
inputValue: '',
//id
nextId: 5,
},
mutations: {
// 为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 = ''
},
},
实现思路:
App.vue 代码如下:
methods: {
// 根据id进行删除
removeItemById(id) {
this.$store.commit('removeItem', id)
},
},
store/index.js 代码如下:
mutations: {
removeItem(state, id) {
const i = state.list.findIndex((x) => x.id === id)
if (i !== -1) {
state.list.splice(i, 1)
}
},
},
实现思路:
change
属性,当列表选项选中状态改变时获取id以及当前选中状态App.vue 代码如下:
cbStatusChanged(e, id) {
const param = {
id: id,
status: e.target.checked
}
this.$store.commit('changeStatus', param)
},
store/index.js 代码如下:
mutations: {
changeStatus(state, param) {
const i = state.list.findIndex((x) => x.id === param.id)
state.list[i].done = param.status
},
},
实现思路:
store/index.js 代码如下:
getters: {
unDoneLength(state) {
return state.list.filter((x) => x.done === false).length
},
},
实现思路:
viewKey
viewKey
的变化,同步更改所有按钮type值,并设置组件选中样式(当然也有更方便的组件,不需要我们自己写)viewKey
的变化,更新列表的数据源,这里用Getters处理App.vue 代码如下:
changeList(key) {
this.$store.commit('changeList', key)
}
store/index.js 代码如下:
mutations: {
changeList(state, key) {
state.viewKey = key
}
},
html代码如下:
<a-button-group>
<a-button
:type="viewKey === 'all' ? 'primary' : 'default'"
@click="changeList('all')"
>全部a-button
>
<a-button
:type="viewKey === 'undone' ? 'primary' : 'default'"
@click="changeList('undone')"
>未完成a-button
>
<a-button
:type="viewKey === 'done' ? 'primary' : 'default'"
@click="changeList('done')"
>已完成a-button
>
a-button-group>
store/index.js 代码如下:
getters: {
infoList(state) {
if (state.viewKey === 'all') {
return state.list
}
if (state.viewKey === 'undone') {
return state.list.filter((x) => x.done === false)
}
if (state.viewKey === 'done') {
return state.list.filter((x) => x.done === true)
}
return state.list
}
},
实现思路:
App.vue 代码如下:
methods: {
clean() {
this.$store.commit('clean')
},
},
store/index.js 代码如下:
mutations: {
clean(state) {
state.list = state.list.filter((x) => x.done === false)
},
},
以上就是关于vuex的入门内容,本文仅仅简单介绍了vuex一些核心概念以及一个todoList待办清单的小例子!欢迎点赞评论收藏,一起学习一起进步!