简书原文:https://www.jianshu.com/p/0546983f5997javascript
一、什么是Vuex
二、什么是“状态管理模式”?
三、什么状况下应该使用 Vuex?
四、Vuex和全局变量的概念区别
五、最简单的store
六、Vuex的简单使用
6.一、vue文件版本
6.二、js文件版本html
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的全部组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。Vuex 也集成到 Vue 的官方调试工具 devtools extension,提供了诸如零配置的 time-travel 调试、状态快照导入导出等高级调试功能。vue
让咱们从一个简单的 Vue 计数应用开始:java
new Vue({ // state data () { return { count: 0 } }, // view template: ` <div>{{ count }}</div> `, // actions methods: { increment () { this.count++ } } })
这个状态自管理应用包含如下几个部分:
一、state,驱动应用的数据源;
二、view,以声明方式将 state 映射到视图;
三、actions,响应在 view 上的用户输入致使的状态变化。
如下是一个表示“单向数据流”理念的极简示意:vuex
可是,当咱们的应用遇到多个组件共享状态时,单向数据流的简洁性很容易被破坏:
一、多个视图依赖于同一状态。
二、来自不一样视图的行为须要变动同一状态。
对于问题一,传参的方法对于多层嵌套的组件将会很是繁琐,而且对于兄弟组件间的状态传递无能为力。对于问题二,咱们常常会采用父子组件直接引用或者经过事件来变动和同步状态的多份拷贝。以上的这些模式很是脆弱,一般会致使没法维护的代码。vue-cli
所以,咱们为何不把组件的共享状态抽取出来,以一个全局单例模式管理呢?在这种模式下,咱们的组件树构成了一个巨大的“视图”,无论在树的哪一个位置,任何组件都能获取状态或者触发行为!
另外,经过定义和隔离状态管理中的各类概念并强制遵照必定的规则,咱们的代码将会变得更结构化且易维护。
这就是 Vuex 背后的基本思想,借鉴了 Flux、Redux、和 The Elm Architecture。与其余模式不一样的是,Vuex 是专门为 Vue.js 设计的状态管理库,以利用 Vue.js 的细粒度数据响应机制来进行高效的状态更新。npm
虽然 Vuex 能够帮助咱们管理共享状态,但也附带了更多的概念和框架。这须要对短时间和长期效益进行权衡。
若是您不打算开发大型单页应用,使用 Vuex 多是繁琐冗余的。确实是如此——若是您的应用够简单,您最好不要使用 Vuex。一个简单的 global event bus 就足够您所需了。可是,若是您须要构建一个中大型单页应用,您极可能会考虑如何更好地在组件外部管理状态,Vuex 将会成为天然而然的选择。app
每个 Vuex 应用的核心就是 store(仓库)。“store”基本上就是一个容器,它包含着你的应用中大部分的状态 (state)。Vuex 和单纯的全局对象有如下两点不一样:
一、Vuex 的状态存储是响应式的。当 Vue 组件从 store 中读取状态的时候,若 store 中的状态发生变化,那么相应的组件也会相应地获得高效更新。
二、你不能直接改变 store 中的状态。改变 store 中的状态的惟一途径就是显式地提交 (commit) mutation。这样使得咱们能够方便地跟踪每个状态的变化,从而让咱们可以实现一些工具帮助咱们更好地了解咱们的应用。框架
/* 安装 Vuex 以后,让咱们来建立一个 store。建立过程直截了当——仅须要提供一个初始 state 对象和一些 mutation: */ // 若是在模块化构建系统中,请确保在开头调用了 Vue.use(Vuex) const store = new Vuex.Store({ state: { count: 0 }, mutations: { increment (state) { state.count++ } } }) /* 如今,你能够经过 store.state 来获取状态对象,以及经过 store.commit 方法触发 状态变动: */ store.commit('increment') console.log(store.state.count) // -> 1 /* 再次强调,咱们经过提交 mutation 的方式,而非直接改变 store.state.count,是因 为咱们想要更明确地追踪到状态的变化。这个简单的约定可以让你的意图更加明显,这样你 在阅读代码的时候能更容易地解读应用内部的状态改变。此外,这样也让咱们有机会去实现一 些能记录每次状态改变,保存状态快照的调试工具。有了它,咱们甚至能够实现如时间穿梭般 的调试体验。 因为 store 中的状态是响应式的,在组件中调用 store 中的状态简单到仅须要在计算 属性中返回便可。触发变化也仅仅是在组件的 methods 中提交 mutation。 */
下载Vuex模块化
vue-cli搭建的项目 利用脚手架搭建项目以后,能够经过npm引入vuex npm install vuex
也能够直接经过引入文件
<script src="/path/to/vue.js"></script>
<script src="/path/to/vuex.js"></script>
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') } const getters = { moreCount: function () { return state.count + 'more' } } export default new Vuex.Store({ state, getters, actions, mutations })
import Vue from 'vue' import App from './App' import store from './store' Vue.config.productionTip = false new Vue({ el: '#app', store, components: { App }, template: '<App/>' })
三、使用store进行状态管理——计数
3.一、相应点击事件发布(dispatch)状态
<template> <div> <div>{{ msg }}</div><br> <div> <button @click="increment()">+</button> <button @click="decrement()">-</button> </div><br> </div> </template> <script> export default { name: 'HelloWorld', data () { return { msg: 'HelloWorld' } }, methods: { increment () { console.log('+++') this.$store.dispatch('increment') }, decrement () { console.log('---') this.$store.dispatch('decrement') } } } </script> <style scoped> </style>
<template> <div> {{ msg }}<br> {{ count }}<br> {{ moreCount }} </div> </template> <script> export default { name: 'SimpleCounter', data () { return { msg: 'SimpleCounter' } }, computed: { count () { return this.$store.state.count }, moreCount () { return this.$store.getters.moreCount } } } </script> <style scoped> </style>
<html> <meta charset="utf-8"> <head> <title>Test</title> </head> <body> <div id="app"> <p>{{ count }}</p> <p> <button @click="increment">+</button> <button @click="decrement">-</button> </p> </div> <script src="./vue.js"></script> <script src="./vuex.js"></script> <script src="./vuex-demo2.js"></script> </body> </html>
const store = new Vuex.Store({ state: { count: 0 }, mutations: { increment: state => state.count++, decrement: state => state.count-- } }) new Vue({ el: '#app', computed: { count () { return store.state.count } }, methods: { increment () { store.commit('increment') }, decrement () { store.commit('decrement') } } })