一、简介
Vuex是服务于Vue.js应用程序的状态管理模式。
vue状态管理分为三部分
- state,驱动应用的数据源
- view,以声明方式将state映射到视图
- actions,响应在view上的用户输入导致的状态变化
vuex的设计思想:在多个组件共享状态时,将该共享状态抽离出来以一个全局单例模式管理。通过定义和隔离状态管理中的各种概念,并通过强制规则维持视图和状态间的独立性,让代码变得更结构化且易维护。
二、安装
npm安装
npm install vuex --save
在模块化的打包系统中,通过Vue.use()安装vuex
(当通过全局script标签引用Vuex时,不需要使用Vue.use()安装)
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
三、Store与State
每一个Vuex应用的核心就是store仓库,store是一个容器,包含应用中大部分的state。
Vuex与单纯的全局对象的区别:
1、Vuex状态存储是响应式的,当vue组件从store中读取state时,若state发生变化,则相应的组件也会相应地得到高效更新。
2、不能直接改变store中的state,改变的唯一途径就是commit mutation。可以更方便跟踪每一个状态的变化。
使用new Vuex.Store()创建store
import Vue from 'vue'
import Vuex from 'vuex'
/*安装Vuex*/
Vue.use(Vuex)
//创建一个store实例
const store = new Vuex.Store({
state: {
count: 0
},
mutations: {
increment(state) {
state.count++
}
}
})
//创建一个组件实例,读取state,修改state
const Counter = {
template: `<div>
<div class="btn" @click='add'>增加</div>
{{count}}</div>`,
computed: {
//将state定义为计算属性
count() {
// return store.state.count
//在根实例vm中注册store以后,所有子组件都能通过this.$store访问到state
return this.$store.state.count
}
},
methods: {
add() {
//修改state必须提交一个commit
// store.commit('increment')
//在根实例vm中注册store以后,所有子组件都能通过this.$store访问到state
this.$store.commit('increment')
}
}
}
//创建一个vue实例,提供一个创建好的store
let vm = new Vue({
el: '#app',
store, //把store对象提供给‘store’选项,可以把store的实例注入所有子组件中
components: {
Counter
}
})
mapState获取多个状态
当一个组件需要获取多个状态时,将这些状态都声明为计算属性会有些重复和冗余,可使用mapState辅助函数帮助我们生成计算属性。
//引入mapState
//import {mapState} from 'vuex'
const mapState = Vuex.mapState
const store = new Vuex.Store({
state: {
count: 0,
isLogin: true,
user: {
username: 'Liane',
id: '1',
gender: 'female'
}
},
mutations: {
increment(state) {
state.count++
}
}
})
const Counter = {
template: `<div>
<div class="btn" @click='add'>增加</div>
<div>{{count}}</div>
<div>{{user.username}}</div>
<div>{{user.id}}</div>
</div>`,
//使用mapState()辅助函数
computed: mapState({
// count() {
// return this.$store.state.count
// }
//count可简化如下
count: state => state.count,
isLogin: state => state.isLogin,
user: state => state.user
}),
methods: {
add() {
this.$store.commit('increment')
}
}
}
let vm = new Vue({
el: '#app',
store,
components: {
Counter
}
})
当映射的计算属性名称与state的子节点名称相同时,也可以给mapState()传递一个字符串数组
computed: mapState([
'count',
'isLogin',
'user'
])
通常我们使用扩展运算符将需要用到的state通过mapState与组件的计算属性混合
computed:{
...mapState([
'count',
'isLogin',
'user'
])
}
四、Getter
当我们需要store中的某些state派生出一些状态时,可以使用Getter,getter就像是store中的计算属性一样,会根据它的依赖被缓存起来,依赖一旦发生改变,就会重新计算。
//定义一个store存储代办事项的状态
const store = new Vuex.Store({
state: {
todos: [
{ id: 1, text: 'study', done: true },
{ id: 2, text: 'exercise', done: true },
{ id: 3, text: 'painting', done: false }
]
},
getters: {
//得到已完成的事项
doneTodos: state => {
return state.todos.filter(todo => todo.done)
},
//得到已完成的事件个数
doneTodosCount: (state, getters) => {
return getters.doneTodos.length
}
}
})
const Counter = {
template: `<div>
<span>已完成{{doneTodosCount}}件代办事项</span>
<ul>
<li v-for="item in doneTodos">
{{item.text}}
</li>
</ul>
</div>`,
computed: {
doneTodos() {
return this.$store.getters.doneTodos
},
doneTodosCount() {
return this.$store.getters.doneTodosCount
}
}
}
let vm = new Vue({
el: '#app',
store,
components: {
Counter
}
})
mapGetter辅助函数
computed: {
...mapGetter([
'doneTodos',
'doneTodosCount'
])
}
若想将getter属性另取名字,可使用对象形式
computed:{
...mapGetter({
doneCount: 'doneTodosCount'
})
}
五、Mutations
更改store中属性的唯一方法就是commit一个mutation。
vuex中的mutation类似事件,每个mutation都有一个字符串的事件类型(type)和一个回调函数(handler)
const mapState = Vuex.mapState
const store = new Vuex.Store({
state: {
isLogin: false,
user: {}
},
mutations: {
setLogin(state, val) {
state.isLogin = val
},
setUser(state, val) {
state.user = val
}
}
})
const Counter = {
data() {
return {
username: ''
}
},
template:
`<div>
<div v-if='isLogin'>
{{user.username}}已登录
<a @click="signOut" href="javascript:;">退出登录</a>
</div>
<div v-else>
<input v-model="username" placeholder="输入用户名">
<div class="btn" @click="submit">登录</div>
</div>
</div>`,
computed: {
...mapState(['isLogin', 'user'])
},
methods: {
submit() {
if (this.username) {
this.$store.commit('setLogin', true)
this.$store.commit('setUser', {
id: 1,
username: this.username
})
}
},
signOut() {
this.$store.commit('setLogin', false)
this.$store.commit('setUser', {})
}
}
}
let vm = new Vue({
el: '#app',
store,
components: {
Counter
}
})
六、Actions
Action类似于mutation,区别:
1、Action提交的是mutation,而不是直接变更状态。
2、Action可以包含任意异步操作
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。