vuex
一、初始步骤
1.安装
npm install vuex --save
2.在src下新建一个store文件夹,里面新建一个index.js文件,并引入vue和vuex
import Vue from 'vue'
import Vuex from 'vuex'
3.引用vuex
Vue.use(Vuex);
4.在main.js中实例化store并引入store下的index.js
二、使用详解
1.官方解释
vuex是一个专为vue.js应用程序开发的状态管理模式
Vuex 的状态存储是响应式的。当 Vue 组件从 store 中读取状态的时候,若 store 中的状态发生变化,那么相应的组件也会相应地得到高效更新
vuex的store在的state是响应式的,当state中的数据发生变化改变时,vue组件会自动更新
这样就必须遵守一些vue对应的规则:
- 提前在store中初始化好所有的属性(要实在想改可以通过vue.set/vue.delete,或者以新对象替换老对象,或者给旧对象重新赋值)
1.使用 Vue.set(obj, 'newNum', 123), 或者 2.以新对象替换老对象 state.obj = { ...state.obj, newNum: 123 }
vuex的使用条件:
- 用户的登录状态,用户名称,头像,地理位置等
- 商品的收藏、购物车中的物品等
vuex的特点:集中式数据管理,一处修改,多处使用
vuex所涉及的参数:
components (组件) ---> actions (异步) ---> mutations (同步,唯一改变state) ---> state (存放数据的仓库) <--- getters (类似于计算属性) <--- components (组件)
2.首先我们来看一下vue官网出的这张图
2.1 mutation—同步,唯一改变state值
从上我们可以了解到vuex的store状态更新的唯一方式就是提交 (commit) mutation,即this.$store.commit('xxxx')->mutations(同步)
以下也包含了mutation常量,即types
组件,
<template>
<div id="app">
<h2>{{$store.state.counter}}</h2>
<button @click="addition">+</button>
<button @click="subtraction">-</button>
<button @click="addCount(5)">+自定义数量</button>
</div>
</template>
<script>
import {INCREAMENT} from './store/mutations-types.js'
export default {
name: 'App',
data(){
return{
message:'我的APP组件',
}
},
methods:{
addition(){
this.$store.commit('increment')
// this.$store.commit(INCREAMENT)
},
subtraction(){
this.$store.commit('decrement')
},
addCount(count){
// payload:负载
// 普通的提交封装
// this.$store.commit('incrementCount',count)
// 特殊的提交封装
this.$store.commit({
type: 'incrementCount',
count
})
},
}
}
</script>
mutations-types.js
export const INCREAMENT = 'increment'
store下的index.js
import Vue from 'vue'
import Vuex from 'vuex'
import {INCREAMENT} from './mutations-types.js'
Vue.use(Vuex)
const store = new Vuex.Store({
state: {
counter: 10,
},
mutations: {
// [INCREAMENT](state){
increment(state){
state.counter++
},
decrement(state){
state.counter--
},
incrementCount(state,count){
// console.log(count)
state.counter+=count
// incrementCount(state,payload){
// state.counter+=payload.count
},
},
actions: {},
getters:{},
modules: {}
})
export default store
2.2 actions—异步
用于异步的actions,即this.$store.dispatch('xxxx')->mutations -> state或mapActions
<template>
<div id="app">
<h2>{{$store.state.counter}}</h2>
<button @click="addition">+</button>
<button @click="subtraction">-</button>
<button @click="addCount(5)">+自定义数量</button>
<h2>{{$store.state.name}}</h2>
<button @click="upInfo">修改信息</button>
</div>
</template>
<script>
export default {
name: 'App',
data(){
return{
message:'我的APP组件',
}
},
methods:{
upInfo(){
this.$store.dispatch('aUpdateInfo')
},
}
}
</script>
store下的index.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const store = new Vuex.Store({
state: {
name:'wwww',
},
mutations: {
updateInfo(state){
//mutation中只适用于同步
// setTimeout(()=>{
// state.name = 'xxxx'
// },1000)
state.name = 'xxxx'
}
},
actions: {
// context上下文
aUpdateInfo(context){
setTimeout(()=>{
context.commit('updateInfo')
},1000)
}
},
getters:{},
modules: {}
})
export default store
2.3 getters—计算属性
getters (store中的计算属性) — 就像计算属性一样,getter 的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被重新计算。
<template>
<div id="app">
<div>counter的平方:{{$store.getters.powerCounter}}</div>
<div>年龄大于等于17:{{$store.getters.moreage}}</div>
<div>年龄大于等于17的数量:{{$store.getters.morelength}}</div>
<div>年龄大于等于传过去的年龄:{{$store.getters.selectage(18)}}</div>
</div>
</template>
store下的index.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const store = new Vuex.Store({
state: {
counter: 10,
students:[
{id: 101, name: 'Lily', age: 16},
{id: 102, name: 'Jhon', age: 17},
{id: 103, name: 'Nacy', age: 18}
],
},
mutations: {},
actions: {},
getters:{
powerCounter(state){ //counter的平方
return state.counter * state.counter
},
moreage(state){ //年龄大于等于17
return state.students.filter(item => item.age >= 17)
},
// 这里的getters代表的是上面的moreage方法
morelength(state,getters){ //年龄大于等于17的数量
return getters.moreage.length
},
selectage(state){ //年龄大于等于传过去的年龄
return age => {
return state.students.filter(item => item.age >= age)
}
}
},
modules: {}
})
export default store
2.4 module—分割模块
module — state是单一状态树(如果把多个状态信息保存到一个store,后面维护就比较困难),为了解决这个问题vuex提供了将store 分割成模块(module)。每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块——从上至下进行同样方式的分割
组件
<template>
<div id="app">
<h2>{{$store.state.a.like}}</h2>
<button @click="updateLike">修改信息</button>
<div>{{$store.getters.likeNum}}</div>
<div>{{$store.getters.likeNum2}}</div>
<div>{{$store.getters.likeNum3}}</div>
</div>
</template>
<script>
export default {
name: 'App',
data(){
return{
message:'我的APP组件',
}
},
methods:{
updateLike(){
this.$store.commit('updateLike','swimming')
}
}
}
</script>
store下的index.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const moduleA = {
state:{
like:'football'
},
mutations:{
updateLike(state,payload){
state.like = payload
}
},
actions:{},
getters:{
likeNum(state){
return state.like + '111'
},
likeNum2(state,getters){
return getters.likeNum + '222'
},
// 用到元素里面的state根
likeNum3(state,getters,rootState){
return getters.likeNum2 + rootState.counter
},
}
}
const store = new Vuex.Store({
state: {
counter: 10,
},
mutations: {},
actions: {},
getters:{},
modules: {
a:moduleA
}
})
export default store