https://vuex.vuejs.org/zh/installation.html
安装
在引入vue之后直接引入vuex可以直接安装
<script src="/path/to/vue.js"></script>
<script src="/path/to/vuex.js"></script>
如果不使用全局的script标签引用的话
也可以使用npm
npm install vuex --save
在模块化的打包系统里,需要显式的通过Vue.use()安装vuex
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
Vuex 依赖 Promise (opens new window)。如果你支持的浏览器并没有实现 Promise (比如 IE),那么你可以使用一个 polyfill 的库,例如 es6-promise (opens new window)。
你可以通过 CDN 将其引入:
<script src="https://cdn.jsdelivr.net/npm/es6-promise@4/dist/es6-promise.auto.js"></script>
然后 window.Promise 会自动可用。
开始使用
每一个vuex应用的核心是store,包含着应用里大部分状态,vuex的状态存储是响应式的,vue组件从store里读取状态的时候,状态一旦变化,组件也相应更新
不能直接改变store里的状态,唯一途径就是显式地提交(commit)mutation(改变)
开始创建一个store
(只需要提供一个初始state对象和一些mutation)
比如创建了一个state里一个count参数
在mutations里定义一个自增函数,里面传入state,对state里的count进行操作
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const store = new Vuex.Store({
state: {
count: 0
},
mutations: {
increment (state) {
state.count++
}
}
})
之后在外面使用commit调用mutations里的increment方法
store.commit('increment')
获取store里的state里的参数
console.log(store.state.count)
为了在vue组件里能访问,需要在new vue根组件的时候用store选项的方式注入store机制
new Vue({
el: '#app',
store: store,
})
如果使用ES6标准的话可以使用ES6对象的property 简写 (用在对象某个 property 的 key 和被传入的变量同名时):
new Vue({
el: '#app',
store
})
之后就可以从组件的方法里提交变更
比如在method里把上面两句话封装成一个局部方法
methods: {
increment() {
this.$store.commit('increment')
console.log(this.$store.state.count)
}
}
提交mutation的方式不是直接改变store.state里的参数,而是利用mutations里的方法改变可以更明确的追踪到状态的变化,阅读代码的时候也可以感受到应用内部的状态改变,能实现一些记录每次状态变化,保存状态快照的调试工具
由于store里的状态是响应式的,所以在组件里调用store里的状态只需要在计算属性里返回,触发变化也仅仅是在组件的 methods 中提交 mutation。
state
vuex使用单一状态树,一个对象包含所有应用层的级状态,所以作为一个为唯一数据源存在,一个应用就包含这一个store实例,这个单一的状态树可以直接定位任意一个特定的状态片段,而且调试过程能轻易取得整个当前应用状态的快照
(单一状态树依然可以模块化–本项目就是把状态和状态变更事件分布到了各个子模块里)
在vue组件里获得vuex状态
存储在vuex里的数据和vue实例里的data状态对象都必须是纯粹的(含有零个或多个的 key/value 对)
从store实例里读取状态最简单的方法是在计算属性里返回某个状态
比如创建一个counter组件,模板里引用count方法,computed里的count方法里返回store里的count参数
// 创建一个 Counter 组件
const Counter = {
template: `<div>{{ count }}</div>`,
computed: {
count () {
return store.state.count
}
}
}
这样每次store里的变化的时候都会重新求计算属性之后更新相关的dom
这种模式导致组件依赖全局状态单例,在模块化的构建系统里,组件会频繁的导入,而且在测试组件的时候需要模拟状态
vuex通过store选项提供了一种把状态从根组件注入到每一个子组件的方式(需调用 Vue.use(Vuex)):
const app = new Vue({
el: '#app',
// 把 store 对象提供给 “store” 选项,这可以把 store 的实例注入所有的子组件
store,
components: { Counter },
template: `
<div class="app">
<counter></counter>
</div>
`
})
在根组件里把store引入之后,component里注册的所有组件就都可以使用this.$store
访问store里的参数和方法了
const Counter = {
template: `<div>{{ count }}</div>`,
computed: {
count () {
return this.$store.state.count
}
}
}
mapstate辅助函数可以在一个组件获取多个状态的时候帮助生成计算属性(减少代码冗余)
mapstate函数返回的是一个对象,如何把它和局部计算属性混合使用?
可以使用一个工具函数把多个对象合并成一个,把最终对象传给computed属性(可以使用对象展开运算符简化写法)
Getter属性
有时候会从store里的state里派生出来一些状态,例如对列表进行过滤并计数:
computed: {
doneTodosCount () {
return this.$store.state.todos.filter(todo => todo.done).length
}
}
如果多个组件需要用到这个属性,比较麻烦
vuex可以在store里定义getter计算属性,其返回值会根据其依赖被缓存起来,只有它的依赖值发生变化才会重新计算,取代在子组件里定义的方法
Getter 接受 state 作为其第一个参数:
const store = new Vuex.Store({
state: {
todos: [
{ id: 1, text: '...', done: true },
{ id: 2, text: '...', done: false }
]
},
getters: {
doneTodos: state => {
return state.todos.filter(todo => todo.done)
}
}
})
getter使用store.getters
的方式访问
getter也可以接受其他 getter 作为第二个参数:
getters: {
// ...
doneTodosCount: (state, getters) => {
return getters.doneTodos.length
}
}
store.getters.doneTodosCount // -> 1
在其他组件里使用
computed: {
doneTodosCount () {
return this.$store.getters.doneTodosCount
}
}
Mutations
处理同步事务
Actions
处理异步事务
=>箭头函数
https://www.cnblogs.com/liyuanhong/articles/10139214.html
=>
是ES6的新增的箭头函数
x => x * x
相当于
function (x) {
return x * x;
}
箭头函数就相当于一个匿名函数,并且简化了函数的定义,还可以包含多条语句
x => {
if (x > 0) {
return x * x;
}
else {
return - x * x;
}
}
如果匿名函数的参数布不止一个,可以使用()包含起来
// 两个参数:
(x, y) => x * x + y * y
// 无参数:
() => 3.14
// 可变参数:
(x, y, ...rest) => {
var i, sum = x + y;
for (i=0; i<rest.length; i++) {
sum += rest[i];
}
return sum;
}
箭头函数与匿名函数的区别
箭头函数内部的this是词法作用域由上下文决定
分析一下项目的store文件夹
一个index.js文件和getter.js文件以及modules文件夹
index.js
是先引入了vue和vuex之后把modules里的各个js文件作为模块引入到新建的vuex的store实例里,还引入了getter.js文件
可以看到里面是没有state和mutations的,只有modules,关于引入的其他js文件export的接口变量里比如app.js
里面是有state和mutations的,所以这种方式是模块化子store,引用的时候可以看一下getter.js文件
所有的子模块里的state里的参数都使用state引用,相当于都是index.js里的vuex.store实例的state