关于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)

}

}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值