1.组件封装radio勾选状态
打开vue组件的源代码,为商品的左侧图片区域添加 radio 组件:
javascript
<!-- 商品左侧图片区域 -->
<view class="goods-item-left">
<radio checked color="#c0c0c0"></radio>
<image:src="goods.goods_small_loge||defaultPic" class="goods_pic"></image>
</view>
当用户点击radio 组件,希望修改当前商品的勾选状态,此时可以为 my-goods 组件绑定 @radio-change 事件,从而获取当前商品Id
javascript
<block v-for="(goods,i) in cart":key="i">
<my-goods :goods="goods" :show-radio="true" @radio-change="radioChange"></my-goods>
</block>
声明如下 mutations 方法,用来修改对应商品的勾选状态:
javascript
updateGoodsState(state,goods) {
const findResult=state.cart.find(x => x.goods_id===goods_id)
if(findResult) {
//更新对应商品的勾选状态
findResult.goods_state=goods.goods_state
//持久化储存到本地
this .commit('m_cart/saveToStorage')
}
}
为 my-goods组件封装 num-change 事件
当用户修改NumberBox 的值以后,可以将最新的商品数量更新到购物车中
javascript
<!-- 商品列表区域 -->
<block v-for="(goods, i) in cart" :key="i">
<my-goods :goods="goods" :show-radio="true" :show-num="true" @radio-change="radioChangeHandler" @num-change="numberChangeHandler">
</block>
在vue组件中,为组件绑定@change事件处理函数:
javascript
<view class="goods-info-box">
<!-- 价格 -->
<view class="goods-price">${{goods.goods_price | tofixed}}</view>
<!-- 数量-->
<uni-number-box :min="1" :value="goods.goods_count"@change="numChangeHandler">
</uni-number-box>
</view>
2.信息储存
创建用户相关的vuex模块,命名为 users.js
javascript
export default {
//开启命名空间
namespaced: true,
// state 数据
state: () => ({
// 收货地址
address: {},
}),
//方法
mutations: {
// 更新收货地址
updataAddress(state,address) {
state.address=address
},
},
// 数据包装器
getters: {},
}
改造组件中的代码,使用vuex提供的address计算属性代替data中定义的本地address对象
javascript
// 按需导入 mapState 和 mapMutations 这两个辅助函数
import { mapState,mapMutations } from'vuex'
export default {
data() {
return {
//address:{}
}
},
methods: {
...mapMutations('m_user',['updateAdderss']),
//选择收货地址
async chooseAddress() {
const [err,succ]=await uni.chooseAddress().catch((err) => err)
//用户成功选择了收货地址
if(err === null&&succ.errMsg === 'chooseAddress:ok') {
//this.address=succ
this.updateAddress(succ)
}
},
},
computed: {
...mapState('m_user',['address']),
//收货详细地址的计算属性
addstr() {
if(!this.address.provinceName)return''
return this.address.provinceName+this.address.cityName+this.address.counyryName+this.address.detailInfa
},
},
}
将Store中的address持久化存储到本地
javascript
export default {
//开启命名空间
namespaced: true,
// state 数据
state: () => ({
// 收货地址
address: JSON.parse(uni.getStorageSy('address')|| '{}'),
}),
//方法
mutations: {
// 更新收货地址
updataAddress(state,address) {
state.address=address
//通过this.commit()方法,调用m_user模块下的 saveAddressToStorage 方法将 address持久化储存到本地
this.commit('m_user/saveAddressToStorage')
},
saveAddressToStorage(state) {
uni.setStorageSync('address',JSON.stringify(state.address))
},
},
// 数据包装器
getters: {},
}
将addstr抽离为getters
目的:为了提高代码的复用性,可以把收货的详细地址抽离为getters,方便在多个页面和组件之间实现复用
javascript
// 数据包装器
getters: {
//收货详细地址的计算属性
addstr(state) {
if(!state.address.provinceName)return''
//拼接 省,市,区的字符串并返回给用户
return this.address.provinceName+this.address.cityName+this.address.counyryName+this.address.detailInfa
}
},
通过 mapGetters 辅助函数函数,将m_user 模块中 addstr 映射到当前组件中使用:
javascript
import { mapState,mapMutations,mapGetters } from'vuex'
export default {
computed: {
...mapState('m_user',['address']),
//将m_user 模块中的 addstr 映射到当前组件中使用
...mapGetters('m_user',['addatr']),
},
}
解决地址授权失败的问题
javascript
async reAuth() {
//提示用户对地址进行授权
const [err2,confirmResult]=await uni.showModal({
content:'检测到您没打开地址权限,是否去设置打开?'
confirmText:"确认",
cancelText:"取消"
})
//如果弹框异常,则直接退出
if(err2)return
//若点击"取消"按钮
if(confirmResult.cancl)return uni.$showMsg('您取消了地址授权!')
//若点击"确认"按钮
if (confirmResult.confirm)return uni.openSetting({
success: (settingResult)=>{
if(settingResult.authSetting['scope.address'])return uni.$showMsg('授权成功')
if(!settingResult.authSetting['scope.address'])return uni.$showMsg('您取消了地址授权')
}
})
}
3.结算组件
动态渲染已勾选商品的总数量
javascript
checkedCount(state) {
//先使用 filter 方法,从购物车中过滤器已勾选的商品
//再使用 reduce 方法,将已勾选的商品总数量进行累加
return state.cart.filter(x => x.goods_state).reduce((total,item)=> total+=item.goods_count,0)
}
通过mapGetters 辅助函数,将需要的getters映射到当前组件中使用:
javascript
import { mapGetters } from'vuex'
export default {
computed: {
...mapGetters('m_cart',['checkedCount'])
},
data() {
return {
}
}
}
动态渲染全选按钮的选中状态
使用 mapGetters 辅助函数,将商品的总数量映射到当前组件中使用,并定义一个叫做 isFullCheck 的计算属性:
javascript
import { mapGetters } from'vuex'
export default {
computed: {
...mapGetters('m_cart',['checkedCount','total']),
// 是否全选
isFullCheck() {
return this.total === this.checkedCount
},
},
data() {
return {
};
}
}
定义一个getters,用来统计已勾选商品总价格:
javascript
//已勾选商品总价
checkedGoodsAmount(state) {
//先使用 filter 方法,从购物车中过滤器已勾选的商品
//再使用 reduce 方法,将已勾选的商品数量 * 单价之后,进行累加
//最后调用 toFixed(2)方法,保留两位小数
return state.cart.filter(x=> x.goods_state)
.reduce((total,item)=>total+=item.goods_count*item.goods_count * item.goods_price,0)
.toFixed(2)
}