艺术之因此存在,
就是为了令人恢复对生活的感受,
为了令人感觉事物,
使石头显出石头的质感。
--什克洛夫斯基
复制代码
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的全部组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。javascript
Vuex 也集成到 Vue 的官方调试工具 devtools extension,提供了诸如零配置的 time-travel 调试、状态快照导入导出等高级调试功能。html
Vuex 能够帮助咱们管理共享状态,并附带了更多的概念和框架。这须要对短时间和长期效益进行权衡。vue
若是您不打算开发大型单页应用,使用 Vuex 多是繁琐冗余的。确实是如此——若是您的应用够简单,您最好不要使用 Vuex。一个简单的 store 模式就足够您所需了。可是,若是您须要构建一个中大型单页应用,您极可能会考虑如何更好地在组件外部管理状态,Vuex 将会成为天然而然的选择。java
总结如下,主要是如下两点:git
主流的几种Vue的组件间传递信息的方式,无非有如下几种:ajax
经过$emit
和props
在父子组件中进行数据传递vuex
用eventbus
(全局事件)在中进行传递vue-cli
利用localstorage、sessionstorage等存储手段来进行传递缓存
毫无疑问,这些个方式都能完成咱们所要的需求,可是在某种程度上面或多或少都有一些问题。例如:安全
利用$emit
和props
在兄弟关系嵌套比较深的状况之下,代码书写量将会大大的增长
全局事件在使用的时候可能被被屡次触发、销毁时机掌握等等一系列的问题,同时做为全局事件全部页面都能监听、掌控事件可能会存在安全性问题等等...
...
针对以上三种传值方式存在各自的缺点,下面着重介绍如下主角Vuex的简单入门。
每个 Vuex 应用的核心就是 store(仓库)。“store”基本上就是一个容器,它包含着你的应用中大部分的状态 (state)。Vuex 和单纯的全局对象有如下两点不一样:
Vuex 的状态存储是响应式的。当 Vue 组件从 store 中读取状态的时候,若 store 中的状态发生变化,那么相应的组件也会相应地获得高效更新。
你不能直接改变 store 中的状态。改变 store 中的状态的惟一途径就是显式地提交 (commit) mutation。这样使得咱们能够方便地跟踪每个状态的变化,从而让咱们可以实现一些工具帮助咱们更好地了解咱们的应用。
上面就将vuex的四个核心选项:state mutations getters actions说了出来,下面咱们经过实例来了解这几个概念。
新建一个.js 文件,名字位置任意,按照惯例,建议在/src/store,咱们就在该文件里编辑代码。
文件位置 /src/store/index.js
// 引入vue 和 vuex
import Vue from 'vue'
import Vuex from 'vuex'
// 这里须要use一下,固定写法,记住便可
Vue.use(Vuex)
// 直接导出 一个 Store 的实例
export default new Vuex.Store({
// 相似 vue 的 data
state: {
name: 'oldName'
},
// 相似 vue 里的 mothods(同步方法)
mutations: {
updateName (state) {
state.name = 'newName'
}
}
})
复制代码
这一步其实就是新建一个store,可是咱们还没在项目中使用。
在入口文件引入上述文件, 并稍微改一下传给 new Vue()的参数,新增的行后面有备注。
文件位置 /src/main.js
import Vue from 'vue'
import App from './App.vue'
import store from './store' //新增
Vue.config.productionTip = false
new Vue({
router,
store, //新增
render: h => h(App)
}).$mount('#app')
复制代码
以上2步,若是咱们使用vue-cli脚手架建立初始化项目的时候,选择了Vuex,以上两步都是默认帮咱们处理好了的,使用起来很方便。
以上2步,其实已经完成了vuex的基本配置,接下来就是使用了。
文件位置 /src/App.vue
<template>
<div>
{{getName}}
<button @click="changeName" value="改名">改名</button>
</div>
</template>
<script> export default { computed:{ getName(){ return this.$store.state.name } }, methods:{ changeName () { this.$store.commit('updateName') } } } </script>
复制代码
这里就是一个很普通的vue文件了,有区别的地方是这里咱们须要用computed属性去获取 store 里的 "data"。
还有就是咱们要改变数据的话,再也不用 this.xxx = xxx
改为 this.$store.commit('updateName')
。
首先是state,如何来获取state的值呢?通常是将这个值放置在computed里面,这样的话一旦数据发生改变的时候,就反馈到页面上面去。
computed:{
getName(){
return this.$store.state.name
}
},
复制代码
state总结:用来存放组件之间共享的数据,它跟组件的data选项相似,只不过data选项是用来存放组件的私有数据。
如今假设逻辑有变,咱们最终指望获得的数据(computed中的getName),是基于 this.$store.state.name
上通过复杂计算得来的,恰好这个getName要在好多个地方使用,那么咱们就得复制好几份。
vuex 给咱们提供了 getter来解决这个问题,能够认为是 store 的计算属性,请看代码:
文件位置 /src/store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
// 相似 vue 的 data
state: {
name: 'oldName'
},
// 相似 vue 的 computed -----------------如下5行为新增
getters:{
getReverseName: state => {
return state.name.split('').reverse().join('')
}
},
// 相似 vue 里的 mothods(同步方法)
mutations: {
updateName (state) {
state.name = 'newName'
}
}
})
复制代码
而后咱们能够这样使用:
文件位置 /src/App.vue
computed:{
getName(){
return this.$store.getters.getReverseName
}
}
复制代码
事实上, getter 不止单单起到封装的做用,它还跟vue的computed属性同样,会缓存结果数据,只有当依赖改变的时候,才要从新计算。
getter总结:getters主要是用来过滤和重组,这些事件最好也是能在计算属性中完成,用于监听事件变化的。
Vuex 中的 mutation 很是相似于事件:每一个 mutation 都有一个字符串的事件类型 (type) 和 一个 回调函数 (handler),且必须是同步方法。
mutation定义:
mutations: {
increment (state, payload) {
state.count += payload.amount
}
}
复制代码
mutation使用:
this.$store.commit('increment', {
amount: 10
})
复制代码
mutations总结:
细心的你,必定发现我以前代码里 mutations 头上的注释了 相似 vue 里的 mothods(同步方法)。
为何要在 methods 后面备注是同步方法呢? 由于mutation只能是同步的函数,只能是同步的函数,只能是同步的函数!!!
那么若是咱们想触发一个异步的操做呢?答案是: action + $dispatch, 咱们继续修改store/index.js下面的代码。
文件位置 /src/store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
// 相似 vue 的 data
state: {
name: 'oldName'
},
// 相似 vue 的 computed
getters:{
getReverseName: state => {
return state.name.split('').reverse().join('')
}
},
// 相似 vue 里的 mothods(同步方法)
mutations: {
updateName (state) {
state.name = 'newName'
}
},
// 相似 vue 里的 mothods(异步方法) -------- 如下7行为新增
actions: {
updateNameAsync ({ commit }) {
setTimeout(() => {
commit('updateName')
}, 1000)
}
}
})
复制代码
而后咱们能够再咱们的vue页面里面这样使用:
文件位置 /src/App.vue
methods: {
rename () {
this.$store.dispatch('updateNameAsync')
}
}
复制代码
actions总结:
actions的做用其实和mutations是没有差异的,无非就是一个同步、异步的差异罢了。而在功能上面主要有一下两个区别:
actions 提交的是mutations,而不是直接变动状态。也就是说,actions会经过mutations,让mutations帮他提交数据的变动
actions 能够包含任意异步操做。ajax、setTimeout、setInterval不在话下
actions第一个参数是一个与 store 实例具备相同方法和属性的 context 对象,所以你能够调用 context.commit 提交一个 mutation,或者经过 context.state 和 context.getters 来获取 state 和 getters,可是 context 对象不是 store 实例自己。下图是我从控制台打印出来的context对象
解释一下这个图:
vuex 的区域是绿色虚线框的位置
流程:
每次 vue 组件须要 给 vuex 分派 一个 actions,actions 提交一个 mutation,由 mutation 来修改 state,而后再返回给 vue 组件渲染
state 状态只能由 mutation 来修改
actions 会能够封装各类 mutation 来进行修改 state
关于 state:state 就是状态
关于 mutation:mutation 是 vuex 对 state 或者 store提交修改的惟一方式,固定方式
关于 getter:
关于 actions:
action 提交的是 mutation,而不是直接变动状态
action 能够包含任意异步操做
下图是我总结的Vuex功能点思惟导图:
参考文献: