vuex初识
为什么要引入 vuex?
vuex是什么?
vuex怎么使用?
1.vuex简介
vuex是vue的一个插件(它并没有遵循一般vue插件的命名规范), 它的目的是对vue应用中多个组件的共享状态进行集中式的管理(读/写).
vue是一个状态自管理应用. 下面是整个vue应用的数据流通图:
State: 驱动整个应用的数据源.
View: 以声明方式将State中的数据映射到视图.
Actions: 响应在View上的用户输入导致的状态变化(包含多种更新状态的方法)
关于多组件共享状态
产生的问题:
- ①多个视图依赖于同一状态.
- ②来自不同视图的行为需要变更同一状态.
之前的解决方法:
- a. 将数据及操作数据的行为都定义在父组件里
- b. 将数据及操作数据的行为传递给需要的各个组件(可能存在多级传递)
而vuex就是用来专门解决这一问题的.
vuex的流程图
2.一个简单的vue计数应用
先使用原始的vue方式实现, 之后一步步改为vuex实现方式.
App.vue:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
| <template> <div> <p>click {{count}} times, count is {{evenOrOdd}}</p> <button @click="increment">+</button> <button @click="decrement">-</button> <button @click="incrementIfOdd">increment if odd</button> <button @click="incrementAsync">increment async</button> </div> </template>
<script> export default { data () { return { count: 0 } }, computed: { evenOrOdd () { return this.count % 2 === 0 ? '偶数' : '奇数' } }, methods: { increment () { const count = this.count this.count = count + 1 }, decrement () { const count = this.count this.count = count - 1 }, incrementIfOdd () { const count = this.count if (count % 2 === 1) { this.count = count + 1 } }, incrementAsync () { const count = this.count setTimeout(() => { this.count = count + 1 }, 1000) } } } </script>
<style scoped>
</style>
|
3.vuex的初步使用
- ①之前项目没有vuex库的需要先安装库: npm install --save vuex
- ②在项目根目录下创建 store.js, vuex的核心管理对象模块. 编写vuex的核心代码
- ③将store模块配置到当前项目中: 在main.js中配置store
main.js:
1 2 3 4 5 6 7 8 9 10 11 12
| import Vue from 'vue' import App from './App' import store from './store'
new Vue({ el: '#app', components: { App }, template: '<App/>', store })
|
$store 对象
配置完 store 后, 所有的组件对象就都多了一个属性对象: $store, 可以用它来实现很多功能.
$store中有两个属性对象: state 和 getters, 也有方法: dispatch(actionName, data) //用来分发调用actions
App.vue:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| <template> <div> <p>click {{count}} times, count is {{evenOrOdd}}</p> <button @click="increment">+</button> <button @click="decrement">-</button> <button @click="incrementIfOdd">increment if odd</button> <button @click="incrementAsync">increment async</button> </div> </template>
<script> import {mapState, mapActions} from 'vuex' export default { computed: { ...mapState(['count']), evenOrOdd () { //这里其实是返回了一个vuex的计算属性(可以理解为返回了一个方法) return this.$store.getters.evenOrOdd } }, methods: { increment () { this.$store.dispatch('increment') }, decrement () { this.$store.dispatch('decrement') }, ...mapActions(['incrementIfOdd', 'incrementAsync']) } } </script>
<style scoped>
</style>
|
store.js:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
|
import Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex) const state = { count: 0 } const mutations = { INCREMENT (state) { state.count++ }, DECREMENT (state) { state.count-- } } const actions = { increment ({commit}) { commit('INCREMENT') }, decrement ({commit}) { commit('DECREMENT') }, incrementIfOdd ({commit, state}) { if (state.count % 2 === 1) { commit('INCREMENT') } }, incrementAsync ({commit, state}) { setTimeout(() => { commit('INCREMENT') }, 1000) } } const getters = { evenOrOdd (state) { return state.count % 2 === 0 ? '偶数' : '奇数' } } export default new Vuex.Store({ state, mutations, actions, getters })
|
这个例子并不适合用vuex来做, vuex是用来解决多组件共享状态问题的. 在这里仅仅用来说明vuex的基本语法.
在真正开发一个项目时, 要综合分析, 有时多组件共享问题用vuex实现也不是很好.
4.vuex的一般项目结构
上面的例子中, 将vuex相关的所有代码, 书写在了一个文件(store.js)中. 但在一般大中型项目中, 会将 vuex 的store.js 拆分为五个文件: index.js、actions.js、getters.js、mutations.js、types.js
- index.js: 创建 state 状态对象, 并将其余几个文件引入后, 向外暴露 store 对象.
- actions.js: 包含多个事件回调函数的对象, 经常用来做一些异步操作(向服务器请求数据等), 之后通过触发 mutations.js 中的方法, 间接的更新 state .
- getters.js: vuex的 state 相关的一些计算属性.
- mutations.js: 包含多个直接更新 state 的方法(回调函数)的对象. 这些方法由 actions.js 中的 commit(‘mutation名’) 触发执行. 注意: 在这里只能执行一些同步代码, 一般只用来同步操作 state .
- types.js: 创建并向外暴露一些对应 mutations.js 方法的字符串常量.
vuex 还有一种 modules 配置, 但是一般用不到. 在一些状态非常非常多的应用中才会使用.