一篇文章帶你深入淺出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

微信公眾號:前端歷劫之路