关于vuex购物车实现的原理

1、模拟购物车功能

   创建store/cart.js

export default {

  state:{

    cartlist: []

  },

  getters: {

    

  },

  actions: {

   

  },

  mutations: {

  }

}

2、添加该模块到状态管理器

import Vue from 'vue'

import Vuex from 'vuex'

import cart from './cart.js'

Vue.use(Vuex)

const store = new Vuex.Store({

  modules: {

    cart

  }

})

export default store

3、cart组件中script.js

import {mapState} from 'vuex'

export default {

  computed: {

    ...mapState({

      'cartlist': ({cart}) => cart.cartlist

    })

  }

}

4、在store/cart.js中请求购物车数据

export default {

  state:{

    cartlist: []

  },

  getters: {

    

  },

  actions: {

        getCartlist ({commit}) {

              cartapi.getCartlist((data) => {commit('changeCartlist', data)})

        }

  },

  mutations: {

  }

}

5、实现请求数据的方法api/cart.js

import axios from 'axios'

export default {

  getCartlist (cb) {

    // axios请求数据,请求成功调用回调函数cb  ----   模拟数据data

    var data = [

      {id:1,name:'pro1',num:1,price:10},

      {id:2,name:'pro2',num:2,price:20},

      {id:3,name:'pro3',num:3,price:30},

      {id:4,name:'pro4',num:4,price:40}

    ]

    

    cb(data)

    

  }

}

6、实现提交mutation改变cartlist----store/cart.js

export default {

  state:{

    cartlist: []

  },

  getters: {

    

  },

  actions: {

        getCartlist ({commit}) {

              cartapi.getCartlist((data) => {commit('changeCartlist', data)})

        }

  },

  mutations: {

        changeCartlist (state, data) {

          state.cartlist = data

        },

  }

}

7、触发请求数据----cart组件中分发action----script.js

import {mapState} from 'vuex'

export default {

  computed: {

    ...mapState({

      'cartlist': ({cart}) => cart.cartlist

    })

  },

  mounted () {

    this.$store.dispatch('getCartlist')

  }

}

8、计算商品的总数量和总价

    8.1 store/cart.js中添加选项getters

export default {

  state:{

    cartlist: []

  },

  getters: {

    totalCount(state){

      let totalNum = 0

      let totalPrice = 0

      state.cartlist.filter((item) => {

          totalNum += item.num * 1

          totalPrice += item.num * item.price

      })

      return {

        totalNum,

        totalPrice

      }

    }

  },

  actions: {

        getCartlist ({commit}) {

              cartapi.getCartlist((data) => {commit('changeCartlist', data)})

        }

  },

  mutations: {

        changeCartlist (state, data) {

          state.cartlist = data

        },

  }

}

    8.2 cart组件中index.vue使用即可

        8.2.1    直接获取store中的getters

<div>总量:{{this.$store.getters.totalCount.totalNum}}</div>

 <div>总价:{{this.$store.getters.totalCount.totalPrice}}</div

        8.2.2   使用mapGetters辅助函数减少代码量

    script.js

import {mapState,mapGetters} from 'vuex'

export default {

  computed: {

    ...mapState({

      'cartlist': ({cart}) => cart.cartlist

    }),

    mapGetters(['totalCount'])

  },

  mounted () {

    this.$store.dispatch('getCartlist')

  }

}

    index.vue

<div>总量:{{totalCount.totalNum}}</div>

 <div>总价:{{totalCount.totalPrice}}</div

9、选择商品计算价格和数量

    9.1 index.vue布局

<template>

  <div>

    <ul>

        <li v-for='(item, index) in cartlist' :key="item.id">

        <input type='checkbox' v-model='item.flag' />

        {{ item.name}} ---- {{item.num}} ---- {{item.price}} -

      </li>

    </ul>

    <div>总量:{{totalCount.totalNum}}</div>

    <div>总价:{{totalCount.totalPrice}}</div>

  </div>

</template>

<script src='./script.js'></script>

<style src="./style.scss"></style>

    9.2 改造源数据 api/cart.js

import axios from 'axios'

export default {

  getCartlist (cb) {

    // axios请求数据,请求成功调用回调函数cb  ----   模拟数据data

    var data = [

      {id:1,name:'pro1',num:1,price:10},

      {id:2,name:'pro2',num:2,price:20},

      {id:3,name:'pro3',num:3,price:30},

      {id:4,name:'pro4',num:4,price:40}

    ]

    data.map((item) => {

      item.flag = false

    })

    cb(data)

    

  }

}

10、 实现全选和反选功能

    10.1 index.vue布局

<template>

  <div>

全选<input type='checkbox' @change="selectFn(cartlist)" v-model='allSelected' />

    <ul>

        <li v-for='(item, index) in cartlist' :key="item.id">

        <input type='checkbox' v-model='item.flag' />

        {{ item.name}} ---- {{item.num}} ---- {{item.price}} -

      </li>

    </ul>

    <div>总量:{{totalCount.totalNum}}</div>

    <div>总价:{{totalCount.totalPrice}}</div>

  </div>

</template>

<script src='./script.js'></script>

<style src="./style.scss"></style>

    10.2 store/cart.js添加新的初始值 allSelected

export default {

  state:{

    cartlist: [],

    allSelected: false

  },

  getters: {

    totalCount(state){

      let totalNum = 0

      let totalPrice = 0

      state.cartlist.filter((item) => {

          totalNum += item.num * 1

          totalPrice += item.num * item.price

      })

      return {

        totalNum,

        totalPrice

      }

    }

  },

  actions: {

        getCartlist ({commit}) {

              cartapi.getCartlist((data) => {commit('changeCartlist', data)})

        }

  },

  mutations: {

        changeCartlist (state, data) {

          state.cartlist = data

        },

  }

}

    10.3 cart组件中添加全选事件

//index.vue

全选<input type='checkbox' @change="selectFn(cartlist)" v-model='allSelected' />

// script.js 中的methods

selectFn (cartlist) {

       this.$store.commit('changeAllSelect')  // 切换真假

        //改变store中数据后立马请求其值

       if(this.$store.state.cart.allSelected){ //  如果为真,表示全部要被选中

         const flag = true  // 标志为真

         this.$store.dispatch('getAllSelectCartlist', {cartlist, flag} ) // action中设置所有元素为真

       }else{

         const flag = false

         this.$store.dispatch('getAllSelectCartlist', {cartlist, flag} )

       }

     },

    10.4 实现changeAllSelect mutation 和 getAllSelectCartlist action

        store/cart.js

export default {

  state:{

    cartlist: [],

    allSelected: false

  },

  getters: {

    totalCount(state){

      let totalNum = 0

      let totalPrice = 0

      state.cartlist.filter((item) => {

          totalNum += item.num * 1

          totalPrice += item.num * item.price

      })

      return {

        totalNum,

        totalPrice

      }

    }

  },

  actions: {

        getCartlist ({commit}) {

              cartapi.getCartlist((data) => {commit('changeCartlist', data)})

        },

         getAllSelectCartlist ({commit}, {cartlist, flag}) {

      cartlist.map((item) => {

        item.flag = flag

      })

      commit('changeCartlist', cartlist)


    },

  },

  mutations: {

        changeCartlist (state, data) {

          state.cartlist = data

        },

         changeAllSelect (state) {

      state.allSelected = !state.allSelected


    },

  }

}

11、点击列表选择实现全选和反选

<ul>

        <li v-for='(item, index) in cartlist' :key="item.id">

        <input type='checkbox' @change='selectItem(cartlist, item, index)' v-model='item.flag' />

        {{ item.name}} ---- {{item.num}} ---- {{item.price}} -- <button @click="deleteItem(cartlist, index)">删除</button>

      </li>

    </ul>

script.js

selectItem (cartlist, item, index) {

       if(item.flag){

         const flag = true

         this.$store.dispatch('selectItem', {cartlist, index, flag}) // cartlist[index].flag = flag

       }else {

         const flag = false

         this.$store.dispatch('selectItem', {cartlist, index, flag})

       }

       // console.log("cartlist",this.$store.state.cart.cartlist)

       var cartlist = this.$store.state.cart.cartlist

       this.$store.dispatch('checkItem',cartlist) // 每做出一次选择就去检测要不要全选

     }

实现action selectItem 和checkItem   store/cart.js

export default {

  state:{

    cartlist: [],

    allSelected: false

  },

  getters: {

    totalCount(state){

      let totalNum = 0

      let totalPrice = 0

      state.cartlist.filter((item) => {

          totalNum += item.num * 1

          totalPrice += item.num * item.price

      })

      return {

        totalNum,

        totalPrice

      }

    }

  },

  actions: {

        getCartlist ({commit}) {

              cartapi.getCartlist((data) => {commit('changeCartlist', data)})

        },

         getAllSelectCartlist ({commit}, {cartlist, flag}) {

      cartlist.map((item) => {

        item.flag = flag

      })

      commit('changeCartlist', cartlist)

    },

selectItem ({commit}, {cartlist, index, flag}) {

      cartlist[index].flag = flag

      commit('changeCartlist', cartlist)

    },

    checkItem ({commit}, cartlist){

      let all = true

      cartlist.map((item) => {

        if(!item.flag) {

          all = false

        }

      })

      commit('checkCartlist', all)

    }

  },

  mutations: {

        changeCartlist (state, data) {

          state.cartlist = data

        },

         changeAllSelect (state) {

      state.allSelected = !state.allSelected

    },

  }

}

实现mutation checkCartlist

export default {

  state:{

    cartlist: [],

    allSelected: false

  },

  getters: {

    totalCount(state){

      let totalNum = 0

      let totalPrice = 0

      state.cartlist.filter((item) => {

          totalNum += item.num * 1

          totalPrice += item.num * item.price

      })

      return {

        totalNum,

        totalPrice

      }

    }

  },

  actions: {

        getCartlist ({commit}) {

              cartapi.getCartlist((data) => {commit('changeCartlist', data)})

        },

         getAllSelectCartlist ({commit}, {cartlist, flag}) {

      cartlist.map((item) => {

        item.flag = flag

      })

      commit('changeCartlist', cartlist)

    },

selectItem ({commit}, {cartlist, index, flag}) {

      cartlist[index].flag = flag

      commit('changeCartlist', cartlist)

    },

    checkItem ({commit}, cartlist){

      let all = true

      cartlist.map((item) => {

        if(!item.flag) {

          all = false

        }

      })

      commit('checkCartlist', all)

    }

  },

  mutations: {

        changeCartlist (state, data) {

          state.cartlist = data

        },

         changeAllSelect (state) {

      state.allSelected = !state.allSelected

    },

checkCartlist (state, data) {

      state.allSelected = data

    }

  }

}

12、删除操作

<ul>

        <li v-for='(item, index) in cartlist' :key="item.id">

        <input type='checkbox' @change='selectItem(cartlist, item, index)' v-model='item.flag' />

        {{ item.name}} ---- {{item.num}} ---- {{item.price}} -- <button @click="deleteItem(cartlist, index)">删除</button>

      </li>

    </ul>

deleteItem (cartlist, index) {

       this.$store.dispatch('deleteItem', {cartlist, index})

     },

store/cart.js

export default {

  state:{

    cartlist: [],

    allSelected: false

  },

  getters: {

    totalCount(state){

      let totalNum = 0

      let totalPrice = 0

      state.cartlist.filter((item) => {

          totalNum += item.num * 1

          totalPrice += item.num * item.price

      })

      return {

        totalNum,

        totalPrice

      }

    }

  },

  actions: {

        getCartlist ({commit}) {

              cartapi.getCartlist((data) => {commit('changeCartlist', data)})

        },

         getAllSelectCartlist ({commit}, {cartlist, flag}) {

      cartlist.map((item) => {

        item.flag = flag

      })

      commit('changeCartlist', cartlist)

    },

selectItem ({commit}, {cartlist, index, flag}) {

      cartlist[index].flag = flag

      commit('changeCartlist', cartlist)

    },

    checkItem ({commit}, cartlist){

      let all = true

      cartlist.map((item) => {

        if(!item.flag) {

          all = false

        }

      })

      commit('checkCartlist', all)

    },

deleteItem ({commit}, {cartlist, index}) {

      cartapi.deleteItem({cartlist, index}, (data) => {commit('changeCartlist', data)})

    },

  },

  mutations: {

        changeCartlist (state, data) {

          state.cartlist = data

        },

         changeAllSelect (state) {

      state.allSelected = !state.allSelected

    },

checkCartlist (state, data) {

      state.allSelected = data

    }

  }

}

api/cart.js

import axios from 'axios'

export default {

  getCartlist (cb) {

    // axios请求数据,请求成功调用回调函数cb  ----   模拟数据data

    var data = [

      {id:1,name:'pro1',num:1,price:10},

      {id:2,name:'pro2',num:2,price:20},

      {id:3,name:'pro3',num:3,price:30},

      {id:4,name:'pro4',num:4,price:40}

    ]

    

    data.map((item) => {

      item.flag = false

    })

    

    cb(data)

    

  },

  deleteItem ({cartlist, index}, cb) {

    cartlist.splice(index, 1)

    cb(cartlist)

  }

}

编辑:千锋HTML5​

猜你喜欢

转载自blog.csdn.net/liuyingv8/article/details/82182330