(六)Vue项目——微商城:实现购物车结算信息、商品数量加减
通过window+Apache+php+MySQL 服务器配置提升对项目开发认识。
目录
购物车
准备购物车数据
放在store中。
src\store\modules\shopcart.js
const state = {
// { id: 商品id, count: 购买数量,selected: false }
car: [],
}
const getters = {}
const actions = {}
const mutations = {}
export default {
namespaced: true,
state,
getters,
actions,
mutations
}
src\store\index.js
import shopcart from './modules/shopcart'
modules: {
user,
shopcart
}
添加商品到购物车
src\store\modules\shopcart.js
const mutations = {
addCar (state, goodsinfo) {
var flag = false
state.car.some(item => {
if (item.id == goodsinfo.id) {
item.count += parseInt(goodsinfo.count)
flag = true
return true
}
})
if (!flag) {
state.car.push(goodsinfo)
}
}
}
src\pages\goods\GoodsInfo.vue
<mt-button type="danger" size="small" @click="addShopcart">加入购物车</mt-button>
addShopcart () {
this.$store.commit('shopcart/addCar', {
id: this.id,
count: this.selectedCount,
selected: true
})
},
再vue-devtools中查看vuex添加结果。
保存购物车数据
将购物车数据保存到localStorage。
src\store\modules\shopcart.js
function setItem(name, item) {
localStorage.setItem(name, JSON.stringify(item))
}
function getItem(name) {
return JSON.parse(localStorage.getItem(name) || '[]')
}
const state = {
car: getItem('car')
}
addCar (state, goodsinfo) {
……(原有代码)
setItem('car', state.car)
}
测试程序,刷新页面,观察购物车里的数据(vuex)是否可以保留。
查询购物车里的商品
src\pages\Shopcart.vue
<script>
import { mapState } from 'vuex'
export default {
computed: {
...mapState('shopcart', ['car']),
},
created () {
this.getGoodsList()
},
methods: {
getGoodsList () {
var idArr = []
this.car.forEach(item => idArr.push(item.id))
if (idArr.length <= 0) {
return
}
window.console.log(idArr)
}
}
}
</script>
到购物车页面查看商品数据是否正常
src\pages\Shopcart.vue
getGoodsList () {
var idArr = []
this.car.forEach(item => idArr.push(item.id))
if (idArr.length <= 0) {
return
}
this.$indicator.open({
text: '加载中'
})
var params = { ids: idArr }
this.$http.get('shopcart', { params: params }).then(res => {
this.$indicator.close()
window.console.log(res.data.data)
})
}
再次查询结果:
this.$http.get('shopcart', { params: params }).then(res => {
this.$indicator.close()
if (res.data.code === 1) {
this.goodslist = res.data.data
}
})
data () {
return {
goodslist: []
}
},
显示购物车页面
src\pages\Shopcart.vue
<template>
<div class="shopcar-container">
<div class="goods-list">
<div class="mui-card">
<div class="mui-card-content" v-for="(item) in goodslist" :key="item.id">
<div class="mui-card-content-inner flex">
<!-- 复选框 -->
<div class="mui-input-row mui-checkbox mui-left">
<label> </label>
<input type="checkbox">
</div>
<!-- 中间商品图片 -->
<img :src="item.image">
<!-- 右侧部分 -->
<div class="info">
<h1>{{ item.name }}</h1>
<p class="flex">
<span class="price">¥{{ item.price }}</span>
<a href="#">删除</a>
</p>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
样式:
<style lang="scss" scoped>
.flex {
display: flex;
}
.shopcar-container {
background: #eee;
overflow: hidden;
.goods-list {
.mui-card-content-inner {
align-items: center;
padding: 10px;
.mui-checkbox.mui-left input[type='checkbox'] {
left: 0px;
}
.mui-radio.mui-left label, .mui-checkbox.mui-left label {
padding-left: 20px;
padding-right: 35px;
padding-bottom: 22px;
}
}
img {
width: 60px;
}
.info {
margin-left: 10px;
width: 100%;
overflow: hidden;
box-sizing: border-box;
h1 {
font-size: 13px;
font-weight: bold;
line-height: 20px;
padding-top: 10px;
}
p {
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
.price {
text-align: left;
font-size: 16px;
font-weight: 700;
color: red;
flex: 1
}
a {
line-height: 25px;
}
}
}
}
}
</style>
向购物车中多添加几件商品,查看页面效果:
显示商品购买数量
复用numbox组件。
src\pages\Shopcart.vue
import numbox from '../components/numbox.vue'
export default {
……(原有代码)
components: {
numbox
}
}
<!-- 右侧部分 -->
<div class="info">
<h1>{{ item.name }}</h1>
<p class="flex">
<span class="price">¥{{ item.price }}</span>
<numbox v-if="item.num" @count="countChange" :max="item.num" :goodsid="item.id"></numbox>
<span v-else style="margin-right:20px;">该商品暂时无货</span>
<a href="#">删除</a>
</p>
</div>
methods: {
……(原有代码)
countChange (goodsinfo) {
window.console.log(goodsinfo)
}
}
页面效果:
此时显示的数量不对,需要算出来。
src\store\modules\shopcart.js
const getters = {
// 获取商品数量
getGoodsCount (state) {
var goods = {}
state.car.forEach(item => {
goods[item.id] = item.count
})
return goods
}
}
src\pages\Shopcart.vue
import { mapGetters, mapState } from 'vuex'
computed: {
...mapState('shopcart', ['car']),
...mapGetters('shopcart', ['getGoodsCount'])
},
<numbox v-if="item.num" @count="countChange" :initcount="getGoodsCount[item.id]" :max="item.num" :goodsid="item.id"></numbox>
通过添加到购物车的方式,将商品100多购买几件,观察结果。
购买数量加减
src\store\modules\shopcart.js
const mutations = {
……(原有代码)
updateGoodsInfo (state, goodsinfo) {
state.car.some(item => {
if (item.id == goodsinfo.id) {
item.count = parseInt(goodsinfo.count)
return true
}
})
setItem('car', state.car)
}
}
src\pages\Shopcart.vue
countChange (goodsinfo) {
this.$store.commit('shopcart/updateGoodsInfo', goodsinfo)
},
测试程序,按“+”或“-”按钮后,商品数量会发生变化。
然后刷新页面,观察商品数量的变化是否会保存。
调整数量框大小
numbox框显得有点大了,修改一下numbox,让它可以可以自定义大小。
在使用的时候,传过来size属性,表示大小。
src\pages\Shopcart.vue
<numbox v-if="item.num" @count="countChange" :initcount="getGoodsCount[item.id]" :max="item.num" :goodsid="item.id" size="min"></numbox>
src\components\numbox.vue
props: ['initcount', 'max', 'goodsid', 'size'],
<template>
<div class="mui-numbox" data-numbox-min="1" :data-numbox-max="max" :style="myStyle">
……(原有代码)
</div>
</template>
data () {
return {
myStyle: {}
}
},
mounted () {
……(原有代码)
if (this.$props.size === 'min') {
this.myStyle = { height: '25px', margin: '0 10px 0px 10px' }
}
},
页面效果:
选中购买的商品
src\store\modules\shopcart.js
const getters = {
……(原有代码)
// 获取商品有没有选中的状态值(selected)
getGoodsSelected (state) {
var goods = {}
state.car.forEach(item => {
goods[item.id] = item.selected
})
return goods
}
}
src\pages\Shopcart.vue
...mapGetters('shopcart', ['getGoodsCount', 'getGoodsSelected'])
<!-- 复选框 -->
<div class="mui-input-row mui-checkbox mui-left">
<label> </label>
<input type="checkbox" v-model="getGoodsSelected[item.id]">
</div>
这时候就全部选中了。
修改商品选中状态
<input type="checkbox" v-model="getGoodsSelected[item.id]" @change="selectedChange(item.id,getGoodsSelected[item.id])">
methods: {
……(原有代码)
selectedChange (id, val) {
this.$store.commit('shopcart/updateGoodsSelected', { id: id, selected: val })
}
}
src\store\modules\shopcart.js
const mutations = {
……(原有代码)
updateGoodsSelected (state, info) {
state.car.some(item => {
if (item.id == info.id) {
item.selected = info.selected
}
})
setItem('car', state.car)
}
}
访问测试,观察取消勾选后,刷新页面,是否能保存。
无货商品禁止购买
src\pages\Shopcart.vue
<input type="checkbox" v-model="getGoodsSelected[item.id]" @change="selectedChange(item.id,getGoodsSelected[item.id])" :disabled="item.num == 0">
getGoodsList () {
……(原有代码)
this.$http.get('shopcart', { params: params }).then(res => {
this.$indicator.close()
if (res.data.code === 1) {
this.goodslist = res.data.data
this.goodslist.forEach(item => {
if (item.num == 0) {
this.selectedChange(item.id, false)
}
})
}
})
},
测试程序,登录后台,将某个购物车里的商品的库存改为0,
然后观察页面效果:
删除购物车中的商品
src\pages\Shopcart.vue
methods: {
……(原有代码)
remove (id, index) {
this.goodslist.splice(index, 1)
this.$store.commit('shopcart/removeCar', id)
}
}
<div class="mui-card-content" v-for="(item, i) in goodslist" :key="item.id">
……(原有代码)
</div>
<a href="#" @click.prevent="remove(item.id, i)">删除</a>
src\store\modules\shopcart.js
const mutations = {
……(原有代码)
removeCar (state, id) {
state.car.some((item, i) => {
if (item.id == id) {
state.car.splice(i, 1)
return true
}
})
setItem('car', state.car)
}
}
测试删除功能。
显示购买的商品数量
在底部Tab栏上显示数量。
只统计选中的商品数量。
src\store\modules\shopcart.js
const getters = {
……(原有代码)
// 获取选中的商品的件数
getSelectedCount (state) {
var count = 0
state.car.forEach(item => {
if (item.selected) {
count += item.count
}
})
return count
}
}
src\components\tabbar.vue
<span class="mui-icon mui-icon-extra mui-icon-extra-cart">
<span class="mui-badge">{{ $store.getters['shopcart/getSelectedCount'] }}</span>
</span>
<span class="mui-tab-label">购物车</span>
测试程序,当商品数量发生变化时,底部显示的购买数量也会随之变化。
购物车结算信息
结算信息包括:选中的商品件数,以及这些商品的总价格。
总件数前面已经实现了。
下面实现总价格的计算。
先获取选中的商品。
src\store\modules\shopcart.js
const getters = {
……(原有代码)
// 获取选中的商品
getSelectedGoods (state) {
var goods = {}
state.car.forEach(item => {
if (item.selected) {
goods[item.id] = item
}
})
return goods
}
}
src\pages\Shopcart.vue
<template>
<div class="shopcar-container">
<div class="goods-list">
……(原有代码)
<!-- 商品结算区域 -->
<div class="mui-card">
<div class="mui-card-content">
<div class="mui-card-content-inner balance">
<div class="left">
<p>总计不含运费</p>
<p>已勾选商品 <span class="red">{{ getSelectedCount }}</span> 件,总价 <span class="red">¥{{ getSelectedAmount }}</span></p>
</div>
<mt-button type="primary">去结算</mt-button>
</div>
</div>
</div>
</div>
</div>
</template>
...mapGetters('shopcart', ['getGoodsCount', 'getGoodsSelected', 'getSelectedCount', 'getSelectedGoods'])
computed: {
……(原有代码)
getSelectedAmount () {
var goods = this.getSelectedGoods
var amount = 0
this.goodslist.forEach(item => {
if (goods[item.id]) {
amount += item.price * goods[item.id].count
}
})
return amount
}
},
样式:
.shopcar-container {
……(原有代码)
.balance {
display: flex;
justify-content: space-between;
align-items: center;
.red {
color: red;
font-weight: bold;
font-size: 16px;
}
}
}
由于现在的商品价格都是0,看不出效果,
先到后台改一下商品价格。
页面效果:
更多推荐
所有评论(0)