文章目录
uni-app & taro 购物车业务逻辑
一、 taro 购物车业务逻辑
1、页面初始渲染业务逻辑
1、发送异步请求 —>判断 返回数据 -->如果未登录,则跳回登录页面 -->若果登陆了判断购物车是否有数据–> 没有数据显示购物车,点击跳转进入商品列表页
componentDidShow () { //在微信小程序中这一生命周期方法对应 onShow
try {
// 本地判断是否登陆
let userid = Taro.getStorageSync('userid')
let token = Taro.getStorageSync('token')
if ( userid && token) {
request({
url: '/cart',
data: {
userid,
token
}
}).then( res => {
console.log(res.data.code)
if (res.data.code === '10119') {
Taro.showToast({
title: '还未登陆,请先登陆',
icon: 'none'
})
Taro.navigateTo({
url: '/pages/login/index'
})
} else if (res.data.code === '10112') {
Taro.showToast({
title: '购物车空空如也,请加购',
icon: 'none'
})
this.setState({
isTrue: true
})
} else {
res.data.data.map( item => {
item.flag = true
})
this.setState({
isTrue: false,
cartlist: res.data.data
}, () => {
this.count() // 用来计算总价和总数
})
}
})
} else {
Taro.showToast({
title: '还未登陆,请先登陆',
icon: 'none'
})
Taro.navigateTo({
url: '/pages/login/index'
})
}
} catch (error) {
}
}
2、异步请求(加、减、删)
/**
index number 点击时是数据的下标
item object 点击时数据下标对应的内容
status string 点击的类型 (加、减、删)
*/
// 异步请求 同步数据 库
numberCompute(index,item,status ){
let token = Taro.getStorageSync('token')
let url = null
let num = null
if(status==="reduce" || status === "add"){
url = "/cart/update"
status==="reduce" ? num = item.num - 1 :num = item.num + 1
}
else url = "/cart/delete"
request({
url,
data :{token,cartid: item.cartid, num },
}).then(res => {
if (res.code === '10019') {
toast({title:'请先登录'})
Taro.navigateTo({
url: '/pages/login/index'
})
} else {
toast({title:'修改数量成功'})
let tempArr = this.state.cartlist
if(status==="add"){
tempArr[index].num += 1
}else if(status==="reduce") {
tempArr[index].num -= 1
}else {
tempArr.splice(index,1)
}
this.setState({ cartlist: tempArr })
// 删除当前的数据 this.setState({})
this.state.cartlist.length === 0 ? this.setState({ flag : true}) : this.setState({ flag : false})
//计算总价格
this.allNumberPrice()
}
})
}
3 、点击触发函数
// 减
reduce(item,ind){
console.log("reduce")
let status = "reduce"
let num = item.num;
if(num>1) {
this.numberCompute(ind,item,status)
}
}
// 加
add(item,ind){
console.log("add")
let status = "add"
this.numberCompute(ind,item,status)
}
// 删
del(item, index){
let status = "del"
this.numberCompute(index, item,status)
}
4、点击选中复选框
给cartlist 中的每条数据添加 一个复选框选中状态
/**
*cartlist 列表数据
* status 全选状态
*/
// 遍历数据 添加cheakbox
filterData(cartlist,status = false) {
cartlist.map((item,index)=>{
return item.cheacked = status
})
计算总数量,和总价格 (每次加、减 、删、点击全选&反选、单击复选框时调用)
// 计算总数量 和 总价格
allNumberPrice(value){
let numer = 0;
let price = 0;
let count= 0;
this.state.cartlist.forEach((item,index)=>{
if(item.cheacked){
count ++
numer += item.num
price += item.price * item.num
}
})
this.setState({
numbertatol:numer,
pricetatol:price
})
count === this.state.cartlist.length ?this.setState({checked : true}) : this.setState({checked : false})
}
点击全选& 全不选
// 点击全选 和全部选
allChoseFn(){
console.log("点击全选")
this.setState({
checked:!this.state.checked,
})
let status = !this.state.checked
this.filterData(this.state.cartlist, status)
//计算总价格
this.allNumberPrice()
}
// 点击选中改变 总数量和总价
choseFn (index) {
console.log("点击单个复选框")
let tempArr = this.state.cartlist
tempArr[index].cheacked = !tempArr[index].cheacked
this.setState({cartlist:tempArr})
this.allNumberPrice()
}
完整 代码
import Taro, { Component } from '@tarojs/taro'
// 为什呢 View 要单独引入,react 说明 组件的首字母一定要大写,小写被当做html标签
import { View
,Image,Text,Checkbox,Navigator,CheckboxGroup
} from '@tarojs/components'
import { AtSwipeAction ,AtInput,AtButto} from "taro-ui"
import {request,toast} from '../../utils/request'
import "./index.scss"
class Index extends Component {
constructor (props) {
super(props)
this.state = {
checked:false,
flag:true,
cartlist:[],
numbertatol: 0,
pricetatol : 0
}
}
componentDidShow(){
this.setState({checked:false})
console.log("diaoyongle")
this.getCartList()
}
getCartList(){
try{
let userid = Taro.getStorageSync('userid')
let token = Taro.getStorageSync('token')
if(userid && token){
request({
url: '/cart',
data: {
userid, token
}
}).then(res=>{
const { code } = res.data
if (code === '10019') {
toast({title:'请先登录'})
Taro.navigateTo({
url: '/pages/login/index'
})
} else if (code === '10012') {
toast({title:'请先选购商品'})
this.setState({ flag :true })
} else {
toast({title:'购物车列表获取成功'})
this.setState({ flag :false , cartlist : res.data.data })
this.filterData(res.data.data)
}
})
}else {
toast({title:'请先登录'})
Taro.navigateTo({
url: '/pages/login/index'
})
}
}catch(e){
console.log(e)
}
}
// 减
reduce(item,ind){
console.log("reduce")
let status = "reduce"
let num = item.num;
if(num>1) {
this.numberCompute(ind,item,status)
}
}
// 加
add(item,ind){
console.log("add")
let status = "add"
this.numberCompute(ind,item,status)
}
// 删
del(item, index){
let status = "del"
this.numberCompute(index, item,status)
}
// 异步请求 同步数据 库
numberCompute(index,item,status ){
let token = Taro.getStorageSync('token')
let url = null
let num = null
if(status==="reduce" || status === "add"){
url = "/cart/update"
status==="reduce" ? num = item.num - 1 :num = item.num + 1
}
else url = "/cart/delete"
request({
url,
data :{token,cartid: item.cartid, num },
}).then(res => {
if (res.code === '10019') {
toast({title:'请先登录'})
Taro.navigateTo({
url: '/pages/login/index'
})
} else {
toast({title:'修改数量成功'})
let tempArr = this.state.cartlist
if(status==="add"){
tempArr[index].num += 1
}else if(status==="reduce") {
tempArr[index].num -= 1
}else {
tempArr.splice(index,1)
}
this.setState({ cartlist: tempArr })
// 删除当前的数据 this.setState({})
this.state.cartlist.length === 0 ? this.setState({ flag : true}) : this.setState({ flag : false})
//计算总价格
this.allNumberPrice()
}
})
}
// 计算总数量 和 总价格
allNumberPrice(value){
let numer = 0;
let price = 0;
let count= 0;
this.state.cartlist.forEach((item,index)=>{
if(item.cheacked){
count ++
numer += item.num
price += item.price * item.num
}
})
this.setState({
numbertatol:numer,
pricetatol:price
})
count === this.state.cartlist.length ?this.setState({checked : true}) : this.setState({checked : false})
}
// // 点击全选 和全部选
allChoseFn(){
console.log("点击全选")
this.setState({
checked:!this.state.checked,
})
let status = !this.state.checked
this.filterData(this.state.cartlist, status)
//计算总价格
this.allNumberPrice()
}
// 点击选中改变 总数量和总价
choseFn (index) {
console.log("点击单个复选框")
let tempArr = this.state.cartlist
tempArr[index].cheacked = !tempArr[index].cheacked
this.setState({cartlist:tempArr})
this.allNumberPrice()
}
// 遍历数据 添加cheakbox
filterData(cartlist,status = false) {
cartlist.map((item,index)=>{
return item.cheacked = status
})
}
render () {
let container = null
if(!this.state.flag){
container = this.state.cartlist.map((item,index)=>{
return (<AtSwipeAction options={[
{
text: '删除',
style: {
backgroundColor: '#FF4949'
}
}
]} onClick={(event)=>{
let status = "del"
if(event.text==="删除") this.numberCompute(index, item, status = "del")
}}>
<View className='normal'>
<CheckboxGroup onChange={this.choseFn.bind(this,index)}>
<Checkbox checked={item.cheacked} color="#ff0000" style="transform:scale(0.7)" />
</CheckboxGroup>
<View><Image src={item.proimg} className="imageClass"></Image></View>
<View className="text" >
<View className="title"> {item.proname}</View>
<View className="price"> ¥{item.price}</View>
</View>
<View className="numberClass">
<Text className="number"> X{item.num} </Text>
</View>
<View className="caoZuoClass">
<Text onClick={this.reduce.bind(this,item,index)}>-</Text>
<AtInput
size="small"
name='value'
type='text'
value={item.num}
/>
<Text onClick={this.add.bind(this,item,index)}>+</Text>
</View>
</View>
</AtSwipeAction>)
})
}
return !this.state.flag ? (<View>
<CheckboxGroup onChange={this.allChoseFn.bind(this)}>
<Checkbox checked={this.state.checked}/>全选
</CheckboxGroup>
{container}
<View class="chose">
<Text>总数量 :{this.state.numbertatol} </Text>
<Text>总价格 :¥{this.state.pricetatol} </Text>
</View>
</View>) :(<View class="header">
购物车空空如也,请 <Text className="navTion"
onClick={()=>{
Taro.switchTab({
url:'/pages/home/index'
})
}}
>选购商品</Text>
</View>)
}
}
export default Index
index.scss 样式
@import "~taro-ui/dist/style/components/swipe-action.scss";
@import "~taro-ui/dist/style/components/button.scss";
@import "~taro-ui/dist/style/components/loading.scss";
@import "~taro-ui/dist/style/components/input.scss";
@import "~taro-ui/dist/style/components/icon.scss";
@import "~taro-ui/dist/style/components/checkbox.scss";
@import "~taro-ui/dist/style/components/icon.scss";
.taro-img__mode-scaletofill{
border: 1px solid #ccc;
height: 90px;
width: 90px;
margin: 5px;
box-sizing: border-box
}
.taro-img{
height: 100px;
width: 100%;
display: flex;
border-bottom:1rpx solid #ccc;
}
.normal{
display: flex
}
.text{
width: 100px;
padding: 3px 5px;
.title{
font-size: 20px;
width:150px;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
}
.price{
font-size: 20px;
}
}
.numberClass{
flex: 1;
font-size: 20px;
display: flex;
align-items: center;
.number{
width: 100%;
text-align: center;
color: red;
}
}
.caoZuoClass{
width: 150px;
align-items: center;
display: flex;
.at-input{
margin-right: 10px;
width: 50px;
height: 40px;;
}
Text{
padding-left:10px ;
}
}
.navTion{
color: #b2a500;
}
.imageClass{
height: 90px;
width: 90px;
}
二、uni-app 购物车业务逻辑
完整代码 业务逻辑同上
<template>
<view class="cart">
<view v-if="flag" class="header">
购物车空空如也,请 <navigator open-type="switchTab" url="/pages/home/home">选购商品</navigator>
</view>
<view v-else>
<view class="prolistItem" v-for="(item , index) of cartlist" :key="index" >
<checkbox-group name="" @change="choseFn(index)">
<checkbox value="cb" :checked="item.cheacked" color="#ff0000" style="transform:scale(0.7)" />
</checkbox-group>
<view class="image"> <image :src="item.proimg"></image> </view>
<view class="text">
<view class="title"> {{item.proname}}</view>
<view class="price"> ¥{{item.price}}</view>
</view>
<view class="number">
<text>X{{item.num}}</text>
</view>
<view class="options">
<text @click="reduce(item)" style="padding:5px 10px" >{{"-"}}</text>
<text @click="add(item)" style="background-color: red;">+</text>
<text @click="del(item, index)">del</text>
</view>
</view>
<view class="chose">
<checkbox-group name="" @change="allChoseFn">
<label><checkbox value="cb" :checked="checked" />{{checked ?'点击全不选' : '点击全选'}}</label>
</checkbox-group>
<text>总数量 :{{numbertatol}} </text>
<text>总价格 :¥{{pricetatol}} </text>
</view>
</view>
</view>
</template>
<script>
import { request, Toast } from '../../utils/index.js'
export default {
data() {
return {
checked:false,
flag:true,
cartlist:[],
numbertatol: 0,
pricetatol : 0
};
},
onShow () {
try{
let userid = uni.getStorageSync('userid')
let token = uni.getStorageSync('token')
console.log(token)
if(userid && token){
request({
url: '/cart',
params: {
userid, token
}
}).then(res=>{
if (res.code === '10019') {
Toast({str:'请先登录'})
uni.navigateTo({
url: '/pages/login/login'
})
} else if (res.code === '10012') {
Toast({str:'请先选购商品'})
this.flag = true
} else {
console.log(res)
Toast({str:'购物车列表获取成功'})
this.flag = false
this.cartlist = res.data
this.filterData(res.data)
}
})
}else {
Toast({str:'请先登录'})
uni.navigateTo({
url: '/pages/login/login'
})
}
}catch(e){
console.log(e)
}
},
methods:{
// 计算总数量 和 总价格
allNumberPrice(){
let numer = 0;
let price = 0;
let count= 0;
this.cartlist.forEach((item,index)=>{
if(item.cheacked) {
count ++
numer += item.num
price += item.price
}
})
this.numbertatol = numer
this.pricetatol = price
if(count === this.cartlist.length) this.checked = true
else this.checked = false
},
// 点击全选 和全部选
allChoseFn(){
this.checked = !this.checked
this.filterData(this.cartlist,this.checked)
//计算总价格
this.allNumberPrice()
},
// 点击选中改变 总数量和总价
choseFn(index){
this.cartlist[index].cheacked = !this.cartlist[index].cheacked
this.allNumberPrice()
},
reduce(item){
let num = item.num;
console.log(num)
if(num>1) {
num -= 1
this.numberCompute(num,item,status = "reduce")
}
},
add(item){
let num = item.num + 1
this.numberCompute(num,item,status = "add")
},
del(item, index){
this.numberCompute("",item,index)
},
// 异步请求 同步数据 库
numberCompute(num,item,status ){
let token = uni.getStorageSync('token')
let url = null
if(status==="reduce" || status === "add") url = "/cart/update"
else url = "/cart/delete"
request({
url,
params :{token,cartid: item.cartid, num : num },
}).then(res => {
console.log(res)
if (res.code === '10019') {
Toast({str:'请先登录'})
uni.navigateTo({
url: '/pages/login/login'
})
} else {
Toast({str:'修改数量成功'})
if(status==="reduce") item.num -= 1
else if (status==="add") item.num +=1
else{
this.cartlist.splice(status , 1) // 删除当前的数据
this.cartlist.length === 0 ? this.flag = true : this.flag = false
}
//计算总价格
this.allNumberPrice()
}
})
},
// 遍历数据 添加cheakbox
filterData(cartlist,status=false) {
cartlist.map((item,index)=>{
return item.cheacked = status
})
}
}
}
</script>
<style lang="scss">
.chose{
text {
margin-left: 10px;
}
}
.cart {
.header{
display: flex;
navigator{
color:#4cd964;
}
}
}
.number{flex: 1;font: 20px/90px "";}
.number text{
color: red;
text-align: center;
}
.prolistItem {
height: 100px;
width: 100%;
display: flex;
border-bottom:1rpx solid #ccc;
image {
border: 1px solid #ccc;
height: 90px;
width: 90px;
margin: 5px;
box-sizing: border-box
}
}
.options{
flex:1;
width: 110px;
display: flex;
align-items: center;
text{
background: #42a44e;
color: #2C405A;
padding: 5px;
margin-left: 10px;
}
}
.price{
font-size: 20px;
}
.title{
font-size: 20px;
width:100%;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
}
.text {
width: 100px;
padding: 3px 5px;
}
</style>