Vuex详解
一、认识Vuex
(一)Vuex是做什么的?
- 官方解释:Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。
- 它采用集中式存储管理 应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
- Vuex 也集成到 Vue 的官方调试工具devtools extension,提供了诸如零配置的 time-travel 调试、状态快照导入导出等高级调试功能。
- 状态管理到底是什么?
- 状态管理模式、集中式存储管理这些名词听起来就非常高大上,让人捉摸不透。
- 其实,你可以简单的将其看成把需要多个组件共享的变量全部存储在一个对象里面。
- 然后,将这个对象放在顶层的Vue实例中,让其他组件可以使用。
- 那么,多个组件是不是就可以共享这个对象中的所有变量属性了呢?
- 等等,如果是这样的话,为什么官方还要专门出一个插件Vuex呢?难道我们不能自己封装一个对象来管理吗?
- 当然可以,只是我们要先想想VueJS带给我们最大的便利是什么呢?没错,就是响应式。
- 如果你自己封装实现一个对象能不能保证它里面所有的属性做到响应式呢?当然也可以,只是自己封装可能稍微麻烦一些。
- 不用怀疑,Vuex就是为了提供这样一个在多个组件间共享状态的插件,用它就可以了。
(二)使用Vuex管理什么状态?
- 有什么状态时需要我们在多个组件间共享的呢?
- 如果你做过大型开放,你一定遇到过多个状态,在多个界面间的共享问题。
- 比如用户的登录状态、用户名称、头像、地理位置信息等等。
- 比如商品的收藏、购物车中的物品等等。
- 这些状态信息,我们都可以放在统一的地方,对它进行保存和管理,而且它们还是响应式的。
(三)单页面的状态管理
- 我们知道,要在单个组件中进行状态管理是一件非常简单的事情,我们看下面的图片
- 这图片中的三种东西,怎么理解呢?
State
:不用多说,就是我们的状态。(你暂且可以当做就是data中的属性)View
:视图层,可以针对State的变化,显示不同的信息。Actions
:这里的Actions主要是用户的各种操作:点击、输入等等,会导致状态的改变。
<template>
<div>
<div>当前计数:{{counter}}</div>
<button @click="counter++">+1</button>
<button @click="counter--">-1</button>
</div>
</template>
<script>
export default {
name: 'HelloVuex',
data() {
return {
counter: 0
}
},
}
</script>
<style scoped>
</style>
- 在这个案例中,我们有木有状态需要管理呢?没错,就是个数counter。
- counter需要某种方式被记录下来,也就是我们的State。
- counter目前的值需要被显示在界面中,也就是我们的View部分。
- 界面发生某些操作时(我们这里是用户的点击,也可以是用户的input),需要去更新状态,也就是我们的Actions
(四)多页面的状态管理
- Vue已经帮我们做好了单个界面的状态管理,但是如果是多个界面呢?
- 多个试图都依赖同一个状态(一个状态改了,多个界面需要进行更新)
- 不同界面的
Actions
都想修改同一个状态(Home.vue
需要修改,Profile.vue
也需要修改这个状态)
- 也就是说对于某些状态(状态1/状态2/状态3)来说只属于某一个试图,但是也有一些状态(状态a/状态b/状态c)属于多个试图共同想要维护的
- 状态1/状态2/状态3你放在自己的房间中,你自己管理自己用,没问题。
- 但是状态a/状态b/状态c我们希望交给一个大管家来统一帮助我们管理!!!
- 没错,
Vuex
就是为我们提供这个大管家的工具。
- 全局单例模式(大管家)
- 我们现在要做的就是将共享的状态抽取出来,交给我们的大管家,统一进行管理。
- 之后,你们每个试图,按照我规定好的规定,进行访问和修改等操作。
- 这就是Vuex背后的基本思想。
(五)Vuex状态管理图例
- 在图例中,Vue官方建议我们通过Vue Components到action,然后在Mutations中修改我们的State,
- Vue官方不建议我们直接修改State,否则Devtools这个官方给我们提供的浏览器调试工具就无法跟踪是哪一个组件修改了State,不利于我们项目的管理。
- 我们可以直接通过Mutations修改State,而Actions主要做异步操作(向后端发送网络请求),Mutations中主要是做同步操作。
二、Vuex的基本使用
(一)简单的案例(计数器)
- 引入Vuex:(类似于Vue-Router的使用方式)
首先,我们需要在某个地方存放我们的Vuex代码,这里,我们先创建一个文件夹
store
,并且在其中创建一个index.js
文件,并在index.js
文件中写入如下代码:
import Vue from 'vue'
import Vuex from 'vuex'
// 1. 安装插件
Vue.use(Vuex)
// 2. 创建对象
const store = new Vuex.Store({
state: {
counter: 0,
},
mutations: {
increment(state) {
state.counter++
},
decrement(state) {
state.counter--
}
}
})
// 3.导出store对象
export default store
- 挂载到Vue实例中
其次,我们让所有的Vue组件都可以使用这个
store
对象,来到main.js
文件,导入store
对象,并且放在new Vue
中
这样,在其他Vue组件中,我们就可以通过this.$store
的方式,获取到这个store
对象了
import Vue from 'vue'
import App from './App'
import store from './store'
Vue.config.productionTip = false
/* eslint-disable no-new */
new Vue({
el: '#app',
store,
render: h => h(App)
})
- 使用Vuex管理counter
<template>
<div>
<h2>{{$store.state.counter}}</h2>
<h2>{{counter}}</h2>
<button @click="increment">+1</button>
<button @click="decrement">-1</button>
</div>
</template>
<script>
export default {
name: 'HelloVuex',
computed: {
counter() {
return this.$store.state.counter
}
},
methods: {
increment() {
this.$store.commit('increment')
},
decrement() {
this.$store.commit('decrement')
}
},
}
</script>
<style scoped>
</style>
- 好的,这就是使用Vuex最简单的方式了。
- 我们来对使用步骤,做一个简单的小结:
- 每一个 Vuex 应用的核心就是
store
(仓库)。“store”
基本上就是一个容器,它包含着你的应用中大部分的状态(state)
- 提取出一个公共的
store
对象,用于保存在多个组件中共享的状态 - 将
store
对象放置在new Vue
对象中,这样可以保证在所有的组件中都可以使用到 - 在其他组件中使用
store
对象中保存的状态即可- 通过
this.$store.state.属性
的方式来访问状态 - 通过
this.$store.commit('Mutations中方法')
的方式来修改状态
- 通过
- 每一个 Vuex 应用的核心就是
注意事项:
- 我们通过显式地提交Mutations的方式,而非直接改变
$store.state.counter
来修改counter
状态。 - 这是因为Vuex可以更明确的追踪状态的变化,同时可以使用官方提供的调试工具跟踪每一次的状态改变,所以不要直接改变
$store.state.counter
的值。