Vuex学习之实现商品列表页

2019-10-17  本文已影响0人  北风吹_yfy
npm install vuex --save
//或
yarn add vuex
  1. 创建store文件夹
//store/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: 100 },
      { name: "马冬梅", price: 20 },
      { name: "马蓉", price: 10 }
    ]
  }
});

//注意new Vuex.Store的Store的S是大写,否则报错为
Uncaught TypeError: vuex__WEBPACK_IMPORTED_MODULE_1__.default.store is not a constructor
  1. 在main.js中引入store
import {store} from './store/store';

new Vue({
    store,
    el:"#app",
    render:h => h(App)
})
  1. 使用数据
//在组件中
//product-list-one.vue中利用computed属性获取store中的数据
export default {
    computed:{
        products(){
            return this.$store.state.products;
        }
    }
}

在完成数据初步渲染之后在组件一种实现改变商品价格的操作

首先获取需要改变的数据,然后在计算属性中对数据进行改变

computed: {
    products() {
      return this.$store.state.products;
    },
    saleProducts() {
      let saleProducts = this.$store.state.products.map(product => {
        return {
          name: "**" + product.name + "**",
          price: product.price / 2
        };
      });
      return saleProducts;
    }
  }

  //将遍历对象改为saleProducts
   <li v-for="(item,index) in saleProducts" :key="index"></li>

但对于多个组价共用次方法则多次复制比较麻烦,需改为以下方式将方法抽离到store.js中的getters

在store.js中

getters:{
    saleProducts:(state) =>  {
      let saleProducts = state.products.map(product => {
        return {
          name: "**" + product.name + "**",
          price: product.price / 2
        };
      });
      return saleProducts;
    }
  }

实现商品降价功能

  1. 在vue中只需在methods中添加一个方法
methods:{
  reducePrice(){
    this.$store.state.products.forEach(product => {
      product.price -= 1;
    })
  }
}
  1. 更改Vuex的store中的状态的唯一方法是提交mutation,Vuex中的mutation非常类似于事件,没个mutation都有一个字符串的事件类型[type]和一个回调函数,这个回调函数就是我们实际运行状态更改的地方,并且他会接受state作为第一个参数。

一般在触发事件时才使用mutation,如果是想要获取数据时就使用getters,想要存储数据时就用state,

//store.js
//触发事件,改变数据
  mutations: {
    reducePrice: state => {
      state.products.forEach(product => {
        product.price -= 1;
      });
    }
  }

//在组件中使用时用commit激活事件,事件触发的事件名字要与store中的事件名字相同
methods: {
    reducePrice() {
      this.$store.commit("reducePrice");
    }
  }

vueX还兼容严格模式。

Actions

Actions提交的是mutation,而不是直接变更的数据状态。

如果实现异步操作应该在Action中实现。

Action是通过store.dispatch触发的。

//store/store.js
actions: {
    reducePrice: context => {
      setTimeout(() => {
        context.commit("reducePrice");
      }, 2000);
    }
  }

//组件中
 methods: {
    reducePrice() {
      // this.$store.commit("reducePrice"); //此处commit是直接触发mutation中的方法
      // 此处应调用actions里的方法
      this.$store.dispatch("reducePrice"); //事件名对应store中actions中的方法名
    }
  }

组件方法中将参数写到分发事件后进行传递,store中通过payload参数进行接收。

//store.js
//触发事件,改变数据
  mutations: {
    reducePrice: (state,payload) => {
      state.products.forEach(product => {
        product.price -= payload;
      });
    }
  },
  actions: {
    reducePrice: (context, payload) => {
      setTimeout(() => {
        context.commit("reducePrice",payload);
      }, 2000);
    }
  }
//组件中
 methods: {
    reducePrice(amount) {
      // this.$store.commit("reducePrice"); //此处commit是直接触发mutation中的方法
      // 此处应调用actions里的方法
      this.$store.dispatch("reducePrice",amount); //事件名对应store中actions中的方法名
    }
  }

辅助函数

<script>

import { mapGetters, mapState, mapActions } from "vuex";

export default {
  computed:{
    // products(){
    //   return this.$store.state.products;
    // },
    ...mapState(["products"]),
    ...mapGetters(["saleProducts"])
  },
  methods:{
     ...mapMutations([
           'increment', // 将 `this.increment()` 映射为 `this.$store.commit('increment')`

           // `mapMutations` 也支持载荷:
          'incrementBy' // 将 `this.incrementBy(amount)` 映射为 
          `this.$store.commit('incrementBy', amount)`
        ]),
        ...mapMutations({
             add: 'increment' // 将 `this.add()` 映射为 `this.$store.commit('increment')`
        })
     ...mapActions(["reducePrice"])
  }
}
</script>

//如果你想将一个 getter 属性另取一个名字,使用对象形式:
mapGetters({
  doneCount:"doneTodosCount"
})
上一篇 下一篇

猜你喜欢

热点阅读