一篇文章帶你深入淺出Vuex
在寫Vuex之前,我們先用一個簡單的例子來實現一個小demo
大家都知道Vue的父傳子用在很多場景,比如像這樣:
父組件:
<template>
<div id="app">
<product-list-one :msg='msg'></product-list-one>
</div>
</template>
<script>
export default {
name: 'app',
components:{
'product-list-one':ProductListOne,
},
data () {
return {
msg:'love'
}
}
}
</script>
子組件:
<template>
<div id="product-list-one">
<div>{{msg}}</div>
</div>
</template>
<script>
props:['msg']
</script>
有父傳子,當然也有子傳父:
子組件:
<template>
<div id="product-list-one">
<button @click="but">點擊</button>
</div>
</template>
<script>
data(){
return {
txt:'hello'
}
},
methods:{
but() {
this.$emit('get',this.txt);
}
}
</script>
父組件:
<template>
<div id="app">
<product-list-one :msg='msg' @get='world'></product-list-one>
</div>
</template>
<script>
import ProductListOne from './components/ProductListOne.vue'
export default {
name: 'app',
components:{
'product-list-one':ProductListOne
},
methods:{
world(data){
console.log(data)
}
}
}
</script>
但是有些場景如果使用父傳子、子傳父的話,很難實現。比如說:
a組件跟b組件相互通信,必須要有一個公共變量庫才更方便。
所以Vuex應運而生,通過創(chuàng)建一個集中的數據存儲,供程序中所有組件訪問。
一、安裝
npm install vuex
二、配置
創(chuàng)建一個store文件夾在根目錄src下,然后在文件夾里創(chuàng)建一個名叫index.js文件。
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export const store = new Vuex.Store({
strict:true,
state:{},
getters:{},
mutations:{},
actions:{}
});
然后在src文件夾下的main.js文件里引入store。
import Vue from 'vue'
import App from './App.vue'
import {store} from './store/store'
new Vue({
store:store,
el: '#app',
render: h => h(App)
})
三、實際操作
Vuex分為四大板塊:
state
getters
mutations
actions
那么我們接下來分別講解一下。
1、state
state用于存儲數據。
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export const store = new Vuex.Store({
strict:true,
state:{
products:[
{name:"馬云",price:200},
{name:"馬化騰",price:140},
{name:"馬冬梅",price:20},
{name:"馬蓉",price:10}
]
}
});
使用this.$store.state.products獲取獲取數據。
<template>
<div id="product-list-one">
<ul>
<li v-for="(product,index) in saleProducts" :key="index">
<span class="name">{{product.name}}</span>
<span class="price">${{product.price}}</span>
</li>
</ul>
</div>
</template>
<script>
export default {
computed:{
products(){
return this.$store.state.products;
}
},
}
</script>
2、getters
getters用于獲取數據。
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export const store = new Vuex.Store({
strict:true,
state:{
products:[
{name:"馬云",price:200},
{name:"馬化騰",price:140},
{name:"馬冬梅",price:20},
{name:"馬蓉",price:10}
]
},
getters:{
saleProducts: (state) =>{
var saleProducts = state.products.map(product =>{
return {
name: "**" + product.name + "**",
price: product.price / 2
};
});
return saleProducts;
}
}
});
調用獲取數據的方法。
<template>
<div id="product-list-one">
<ul>
<li v-for="(product,index) in saleProducts" :key="index">
<span class="name">{{product.name}}</span>
<span class="price">${{product.price}}</span>
</li>
</ul>
</div>
</template>
<script>
import {mapGetters} from 'vuex'
export default {
computed:{
...mapGetters([
"saleProducts"
])
}
}
</script>
3、mutations
mutations用于變更state中的狀態(tài)。
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export const store = new Vuex.Store({
strict:true,
state:{
products:[
{name:"馬云",price:200},
{name:"馬化騰",price:140},
{name:"馬冬梅",price:20},
{name:"馬蓉",price:10}
]
},
getters:{
saleProducts: (state) =>{
var saleProducts = state.products.map(product =>{
return {
name: "**" + product.name + "**",
price: product.price / 2
};
});
return saleProducts;
}
},
mutations:{
reducePrice: (state,payload) =>{
state.products.forEach(product =>{
product.price -= payload;
})
}
}
});
mutations更像是事件注冊,所以需要我們需要store.commit()觸發(fā)一下。
<template>
<div id="product-list-one">
<ul>
<li v-for="(product,index) in saleProducts" :key="index">
<span class="name">{{product.name}}</span>
<span class="price">${{product.price}}</span>
</li>
</ul>
<button @click="reducePrice(2)">商品降價</button>
</div>
</template>
<script>
import {mapGetters} from 'vuex'
export default {
computed:{
products(){
return this.$store.state.products;
},
...mapGetters([
"saleProducts"
])
},
methods:{
reducePrice (n) {
this.$store.commit('reducePrice',n);
}
}
}
</script>
4、actions
actions用于提交的是mutations,而不是直接提交狀態(tài)。
actions可以包含任意異步操作。
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export const store = new Vuex.Store({
strict:true,
state:{
products:[
{name:"馬云",price:200},
{name:"馬化騰",price:140},
{name:"馬冬梅",price:20},
{name:"馬蓉",price:10}
]
},
getters:{
saleProducts: (state) =>{
var saleProducts = state.products.map(product =>{
return {
name: "**" + product.name + "**",
price: product.price / 2
};
});
return saleProducts;
}
},
mutations:{
reducePrice: (state,payload) =>{
// setTimeout(function(){
state.products.forEach(product =>{
product.price -= payload;
})
// },3000);
}
},
actions:{
reducePrice:(context,payload) =>{
setTimeout(function(){
context.commit("reducePrice",payload); // context.commit()相當于 this.$store.commit(),觸發(fā)mutations事件。
},2000);
}
}
});
需要用store.dispatch()觸發(fā)actions,但是為了方便,我們這里使用mapActions。
<template>
<div id="product-list-one">
<ul>
<li v-for="(product,index) in saleProducts" :key="index">
<span class="name">{{product.name}}</span>
<span class="price">${{product.price}}</span>
</li>
</ul>
<button @click="reducePrice(2)">商品降價</button>
</div>
</template>
<script>
import {mapGetters} from 'vuex'
import {mapActions} from 'vuex'
export default {
props:['msg'],
data(){
return {
txt:'hello'
}
},
computed:{
products(){
return this.$store.state.products;
},
...mapGetters([
"saleProducts"
])
},
methods:{
...mapActions([
"reducePrice"
])
}
}
</script>
好了,這就是簡單的Vuex入門,謝謝大家
作者:Vam的金豆之路
主要領域:前端開發(fā)
我的微信:maomin9761
微信公眾號:前端歷劫之路