0.什么是Vuex
vuex是管理数据状态的一个库,通过创建一个集中的数据存储,供所有组件去访问,类似于Java中一个static的Map。
![](https://img.haomeiwen.com/i17789247/656e058c6bb7ab61.png)
上图中,【根组件】可以通过prop给【组件1】、【组件2】,【组件1】和【组件2】再通过prop给【详情组件】和【添加组件】传值。
如果【添加组件】想要更改数据,这时需要触发event传值给【组件2】,【组件2】再触发event传值给【根组件】,【根组件】值变化会分别往下传递。
如果现在【添加组件】和【详情组件】共用一个数据,这就很麻烦了,使用vuex解决这个问题。
![](https://img.haomeiwen.com/i17789247/9c4c47305c9de78b.png)
vuex有store专门存储数据,如果【组件2】想要获取数据,可以使用getter,如果【添加组件】想要更改数据,可以使用mutation。
1.使用vuex
//安装
npm install vuex --save
新建store.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export const store = new Vuex.Store({
state:{
products:[
{name:'马云',price:200},
{name:'马化腾',price:140},
{name:'马冬梅',price:20},
{name:'马蓉',price:5},
]
}
})
main.js
import {store} from './store/store'
new Vue({
el:'app',
store,
router,
render: h=>h(APP)
})
组件中使用
<template>
<div>
<ul>
<li v-for="(item, index) in products" :key="index">{{item.name}}</li>
</ul>
</div>
</template>
<script>
export default {
data () {
return {
products:[]
}
},
methods: {
},
created() {
this.products = this.$store.state.products
}
}
</script>
2.Getters
store.js
export default new Vuex.Store({
state: {
products:[
{name:'马云',price:200},
{name:'马化腾',price:140},
{name:'马冬梅',price:20},
{name:'马蓉',price:5}
]
},
getters: {
saleProducts:(state) => {
let saleProducts = state.products.map(product => {
return {
name: '**' +product.name+ '**',
price: product.price/2
}
})
return saleProducts
}
}
}
组件中
<script>
created() {
this.products =this.$store.getters.saleProducts
}
</script>
3.Mutations
作用:更改Vuex的store中的状态的唯一方法是提交Mutation
store.js
export const store = new Vuex.Store({
strict: true, //严格模式改变vuex值时必须使用Mutation,不能直接改
state:{
products:[
{name:'马云',price:200},
{name:'马化腾',price:140},
{name:'马冬梅',price:20},
{name:'马蓉',price:5},=
]
},
mutations: {
reducePrice: (state) => {
state.products.forEach(product => {
product.price -= 1
})
}
}
})
组件中
<script>
export default {
methods: {
reducePrice:function(){
this.$store.commit('reducePrice')
}
}
}
</script>
4.Actions
1.使用Action解决的问题
在store.js里mutations的reducePrice()方法中,假设修改值需要请求后台获取结果后再操作,此时方法内是异步调用,我们使用setTimeout模拟异步操作。
export default new Vuex.Store({
state: {
products:[
{name:'马云',price:200},
{name:'马化腾',price:140},
{name:'马冬梅',price:20},
{name:'马蓉',price:5}
]
},
mutations: {
reducePrice: (state) => {
//模拟发送请求获取数据
setTimeout(()=>{
state.products.forEach(product => {
product.price -= 1
})
},2000)
}
}
})
组件中调用方法
methods: {
reducePrice:function(){
this.$store.commit('reducePrice')
}
}
此时点击触发reducePrice()方法,结果如下图
![](https://img.haomeiwen.com/i17789247/de2f86388821fc7f.png)
上图中, mutations早已触发,但是因为方法内部是异步的,页面值会延迟2s修改,在开发过程中,调试时会存在误解。
解决方法就是:用action让数据发生变化同时触发reducePrice方法。
2.如何使用Action
store.js
export const store = new Vuex.Store({
strict: true, //严格模式改变vuex值时必须使用Mutation,不能直接改,不要在发布环境下启用严格模式!
state:{
products:[
{name:'马云',price:200},
{name:'马化腾',price:140},
{name:'马冬梅',price:20},
{name:'马蓉',price:5},=
]
},
mutations: {
reducePrice: (state, payload) => {
state.products.forEach(product => {
product.price -= payload
})
}
},
actions: {
reducePriceAction:(context, payload) => {
setTimeout(function(){
context.commit("reducePrice",payload)
},2000)
}
}
})
组件中
<script>
export default {
methods: {
reducePrice:function(amount){
this.$store.dispatch("reducePriceAction",this.amount)
}
}
}
</script>
此时,点击按钮,2s后改变值的同时触发mutations的reducePrice()方法
![](https://img.haomeiwen.com/i17789247/fb5224cca25625ef.png)
5.Mapping Actions & Getters
如果store.js中getter或actions有很多方法,组件使用时候得一个一个写,比较麻烦,使用...mapGetters和...mapActions解决。
1.使用...mapGetters
<template>
<div>
<ul>
<li v-for="(item, index) in saleProducts" :key="index">{{item.name}}</li>
</ul>
</div>
</template>
<script>
import { mapGetters } from 'vuex'
export default {
computed: {
...mapGetters([
"saleProducts"
])
}
}
</script>
2.使用...mapActions
<template>
<div>
<button @click="reducePriceAction">减价</button>
<ul>
<li v-for="(item, index) in products" :key="index">{{item.price}}</li>
</ul>
</div>
</template>
<script>
import { mapActions } from 'vuex'
export default {
methods: {
...mapActions([
'reducePriceAction'
])
//或者这样写也可以 <button @click="reducePrice">减价</button>
//...mapActions({
// reducePrice:'reducePriceAction'
//})
}
}
</script>
网友评论