Vuex的介绍与入门使用
写在前面
学习Vue这样的前端框架,相信大家都会接触到Vuex,但是所谓的Vuex到底是什么呢?又到底应该怎么在自己的项目里面运用呢?作为自学前端的小白,学习Vuex的过程中也是充满了艰辛,翻阅了很多其他前端论坛上的博客,啃了很久的官方文档,真正理解了以后回头看才发现,Vuex真的不难!所以就萌生了自己写一篇通俗易懂的Vuex介绍与使用的文章的想法,希望用自己的理解给其他自学前端的同学带来一定帮助!
PS. 看这篇文章以前默认大家已经对Vue有了一定的了解,并且有用Vue或者Vue-CLI开发项目的经验了,如果没有的话,建议先学习Vue哦~
什么是Vuex?
Vuex是一种状态管理工具(state management pattern),要理解这个概念,首先要明白什么是状态。
状态(State
),说白了就是数据,也就是在Vue实例中data () { return { } }
里面的内容,因为用Vue开发的页面是以一个一个的组件(component)构成的,正常情况下每一个组件的状态是私有的。当项目不是很大,页面不是很复杂的情况下,这似乎没什么问题,但是当我们的应用开始变得复杂,数据需要在不同层级的组件之间流通的时候,Vuex就可以大显身手了。
何为状态管理?
状态实现共享,不同的组件状态肯定会发生改变,Vuex就可以将这些改变统一起来管理,这里结合官网的图来进行讲解【学完以后你会发现这张图真的非常的深刻和形象】。
这里又出现了两个新的概念Mutation
和Action
。Mutation字面理解就是突变、改变,也就是说state的改变就叫mutation,比如计数器的例子中的
addCount(){
this.Count++
}
就可以称作一个Mutation,它一般是一个函数或者方法。注意!Mutation一定是同步操作!方法中不能包含异步请求,异步操作一定要放到Action中。所以我们请求后端接口数据的操作一定都是放在Action中的。Action中会产生Mutation,Mutation又会去改变State。这样所有的State的变化可以非常方便的被我们观察和记录到,便于集中进行管理和调试,这就是Vuex存在的意义。
如何在项目中使用Vuex
在已经存在的Vue-CLI项目中引入Vuex具体操作如下
npm install vuex
随后在项目文件夹下面新建一个store.js文件,在一个模块化的打包系统中,必须显式地通过 Vue.use() 来安装 Vuex:
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
随后将需要进行共享的状态放入一个state对象中
const state = {
songList: [],
isPlay: false
}
当其中一个组件有一个按钮想要播放或者暂停歌曲,就会改变isPlay
的值,以及一个方法需要改变songList
的值,那么就需要定义相应的Mutation
const mutations = {
play (state) {
state.isPlay = true
},
pause (state) {
state.isPlay = false
},
setSongList(state, {songList: songList}) {
state.songList = songList
}
mutation是一个对象,其中有一些我们自己写的方法,注意这些方法传入的第一个参数一定是state,也就是前面我们自己定义的state,所以在mutation中可以获取到所有的state中的属性从而对它们进行改变。第二个参数可以是其他对象,它被称作载荷(payload)。
接下来是action。action的方法传入的第一个参数是context
,它是一个对象,并且拥有store对象所拥有的的全部属性和方法,后面的参数可以自己定义。
比如我想通过axios去后端接口根据search
关键词查找歌曲,得到歌曲列表,然后将其赋值给之前定义的songList
,便需要在action中编写一个异步请求,而改变songList
的值则需要去提交(commit)之前定义的setSongList
这个mutation。
const actions = {
getSongList (context) {
axios.get('/api/song/search&keywords=' + context.state.search)
.then(res => {
context.commit('setSongList', {songList: res.data.songs})
},err => {
console.log(err)
})
上面例子中search
正是我们定义在state中的search
,代表用户输入的搜索歌曲的关键词。关于v-model绑定的值与Vuex的state只允许通过mutation改变相冲突的问题,我采用的是官方给出的的解决方法:定义这个属性的get和set方法,在get中读取state中的该值,在set中commit改变这个数据的mutation,代码如下:
search() {
get() {
return this.$store.state.search
}
set(value) {
this.$store.commit('changeSearch', {search: value})
}
}
总而言之到目前为止我们已经将组件中需要的数据和同步异步方法都在同一个文件中定义出来了,最后只需要new一个store实例并将其导出,就可以在所有组件中使用了
export default new Vuex.Store({
state,
mutations,
actions
})
这里采用了ES6的简写{ state: state }
可以简写为{ state }
在Vue组件中获得Vuex中的状态
在组件中获得State的基本方法是通过计算属性
computed: {
songList () {
return this.$store.state.songList
}
}
在组件中使用Mutations需要使用store.commit()方法,该方法传入的第二个参数称作载荷(payload),它一般是一个对象
this.$store.commit('setSongList', {songList: songList})
在组件中使用Actions则需要通过store.dispatch()方法,Actions 支持同样的载荷方式进行分发
this.$store.dispatch('getSongList')
官方给出了mapState,mapMutation,mapActions
辅助函数,帮我们快速的将Vuex中的内容映射到每一个组件中,用法如下
// 这是songList.vue文件
<script>
import { mapState, mapMutations, mapActions } from 'vuex'
export default {
name: 'songList',
computed: {
...mapState([
'songList'
])
},
methods: {
...mapMutations([
'setSongList'
]),
...mapActions([
'getSongList'
])
}
}
</script>
这样在我们的组件中就可以直接的去使用songList
变量,setSongList
和getSongList
方法,就如同这个方法是在组件内部定义的一样。
<template>
<div>
<button @click='setSongList'></button>
<button @click='getSongList'></button>
<ul>
<li v-for="item in SongList">{{ item.name }}</li>
</ul>
</div>
</template>
至此为止我们就已经可以在一个Vue应用中使用Vuex了。
怎么样,是不是也不是特别复杂?使用了Vuex最大的好处是在调试过程中,可以获得时光回溯般的调试体验,因为每一次状态的改变都是有迹可循的。【这需要我们安装Vue-devtools插件】
当然关于Vuex还有很多更深层次的东西,以上都是我对Vuex一些粗浅的理解,有很多不足之处,欢迎大家指正讨论~