taro 实现购物车逻辑的实例代码


Posted in Javascript onJune 05, 2020

taro 实现购物车逻辑

效果

taro 实现购物车逻辑的实例代码

taro是什么?

Taro 是一套遵循 React 语法规范的 多端开发 解决方案。

  • 现如今市面上端的形态多种多样,Web、React-Native、微信小程序等各种端大行其道,当业务要求同时在不同的端都要求有所表现的时候,针对不同的端去编写多套代码的成本显然非常高,这时候只编写一套代码就能够适配到多端的能力就显得极为需要。
  • 使用 Taro,我们可以只书写一套代码,再通过 Taro 的编译工具,将源代码分别编译出可以在不同端(微信/百度/支付宝/字节跳动/QQ/京东小程序、快应用、H5、React-Native 等)运行的代码。本代码是基于Taro UI 开发的,虽然是基于 taro框架开发的,但购物车的整体逻辑与微信小程序逻辑是基本一样的
  • Taro UI是一款基于 Taro 框架开发的多端 UI 组件库

需要安装taro ui

$ npm install taro-ui

taro官方文档

taroUI 官方文档

cart/index.jsx页面代码
import Taro, { Component } from '@tarojs/taro'
import { View, Checkbox, CheckboxGroup } from '@tarojs/components' 
//用到了taro的三个组件
//想了解可以去查看taro的官方文档
import './index.scss'
import { AtButton, AtInputNumber, AtCard } from 'taro-ui'
import { request, toast } from '../../utils/index'

class Index extends Component {
 constructor(props) {
  super(props)
  this.state = {
   message: '', //购物车为空时显示的信息
   cartdata: [], //购物车的数据列表
   isactive: false, //全选按钮是否选中
   check:false, //单个商品购物车是否被选中
   totalnum:0, //总数量
   totalprice:0, //总价格
   activedata:[] //复选框选中的数据列表
  }

 }
 componentDidShow () {
  //获取购物车数据
  try {
   const token = Taro.getStorageSync('token') //这两个数据是我在登录页面,登录时添加到本地的token和用户id
   const userid = Taro.getStorageSync('userid')
   if (token) { //如果登录了
    const usrename = Taro.getStorageSync('username') //同样登录时添加到本地的用户名
    Taro.setNavigationBarTitle({ //改变导航栏的标题
     title: usrename + '---购物车'
    })
    request({ //这里的request是封装后的方法
     url: '/cart', //接口
     data: { //需要传递的数据
      token,
      userid
     }
    }).then(res => { 
     console.log(res.data)
     const { code } = res.data 
     if (code === '10119') { //后端返回的值 ,判断状态
      toast({ title: '登录已经过期,请从新登录' })
      Taro.navigateTo({  //跳转到登录页
       url: '/pages/login/index'
      })
     } else if (code === '10012') { 
      this.setState({
       message: '购物车空空如也'
      })
     } else {
     //因为taro是基于react的,在react中,状态不能直接改变,要用this.setState
      this.setState({ //登录成功,购物车有数据时,将购物车的列表数据添加到购物车数据中 
       cartdata: res.data.data
      })
     }
    })
   } else { //如果没登录
    toast({ title: '请登录' })
    Taro.navigateTo({ //跳转到登录页面
     url: '/pages/login/index'
    })
   }

  } catch (e) {

  }
 }
 componentDidUpdate(){
  //计算总数量,总价格
  let num=0;
  let price=0;
  if(this.state.activedata.length!=0){ //如果选中的数组长度不为0时,就是有商品被选中了
   this.state.activedata.map((item)=>{ //map遍历数组
    num+= +item.num  //将数量相加 + 号为一元运算符,将字符串类型转换为数值类型
    price+=item.num*item.price  //求价格
   }) 
   this.setState({ //设置值
    totalnum:num,
    totalprice:price
   })
  }else{ //如果没有商品被选中
   this.setState({
    totalnum:0,
    totalprice:0
   })
  }
  
 }
 render() {
  return ( //结构开始
   <View>{
    this.state.message.length === 0 ? null : //如果 message不为空的话,就代表着购物车没有数据,所以显示购物车空空如也,去选购,如果为空,代表着购物车有数据,不显示
     <View onClick={() => { //点击事件 去主页选购商品
      Taro.switchTab({
       url: '/pages/home/index'
      })
     }}> {this.state.message}去选购</View>
   }
    <Checkbox checked={this.state.isactive} onClick={()=>{ //全选按钮 check代表着按钮是否选中 因为taro中的checkbox的onchange方法,不支持小程序,所以没办法,只能用 onClick方法
     let active=!this.state.isactive   //实现点击选中状态取反
     this.setState({  
      isactive:active
     })
     if(active===true){ //如果全选,就代表着 购物车的所有商品都被选中,所以,将购物车列表数据全给选中的数组,将单个商品的状态全部设为选中
      this.setState({
       check:true,
       activedata:this.state.cartdata
      })
     }else{//否则,选中商品数组为空,将单个商品的状态全部设为未选中
      this.setState({
       check:false,
       activedata:[]
      })
     }
    }}>全选</Checkbox>

    <CheckboxGroup  onChange={(evt)=>{ //复选框组,<CheckboxGroup/>中选中项发生改变是触发 change 事件,detail = value:[选中的 Checkbox 的 value 的数组]
     const {detail:{value}}=evt 
     if(value.length===this.state.cartdata.length){ //选中的数组的长度如果等于购物车列表的长度是全选
      this.setState({  
       isactive:true,  //全选按钮被选中
       activedata:this.state.cartdata  //选中商品数组为购物车的列表数组
      })
     }else{ //否则未全选
      var i;
      var data=[];
      for ( i in value){  //因为value数组里的值为选中的checkbox的value的值,我设置的为cartid
       data.push(...(this.state.cartdata.filter(item=>{ //过滤下购物车的列表数据,将cartid相等的对象取出来,放进data数组中,...是展开运算符,加他是因为在控制台打印的时候发现,每个对象外面都加了一个【】,没办法,这里应该是有简单的写法的,但因为当时累了,也没有细想,就只能写成这样了,
        return item.cartid==value[i]
       })))
      }
      console.log(data,this.state.cartdata)
      this.setState({
       isactive:false,//全选按钮未被选中
       activedata:data //设置选中商品的数组
       //至此,计算总数量,总价格、全选、单选的逻辑就全完成了,至于为什么写成这样,是因为taro是基于react的标准的,没有计算属性,没有双向绑定
      })
     }
    }}>
     {
      this.state.cartdata.map((item, index) => //循环显示购物车数据
       <AtCard
        title={item.proname}
        thumb={item.proimg}
        extra={'$'+item.price}
        key={item.proid}

       >
        <View><Checkbox value={item.cartid} checked={this.state.check}></Checkbox> 
        {/* 每个商品前的复选框 */}
         <AtInputNumber //数量加减
          min={0}
          max={10}
          step={1}
          value={item.num} //之间的值
          onChange={this.change.bind(this, item,index)} //onchange输入框值改变时触发的事件,开发者需要通过 onChange 事件来更新 value 值变化,onChange 函数必填
         />
         <AtButton type='primary' size='small' onClick={this.del.bind(this,item)}>删除</AtButton> 
         {/* 删除按钮 */}
        </View>

       </AtCard>
      )
     }
    </CheckboxGroup>
    <View>总数量:{this.state.totalnum}</View>
    <View>总价格:{this.state.totalprice}</View>
   </View>
  )
 }
 del(item){ //删除方法
 //item代表着商品的数据 
  try{
   const token = Taro.getStorageSync('token')
   if(token){ //如果有token值
    request({ //数据请求   删除接口
     url: '/cart/delete',
     data: {
      token,
      cartid: item.cartid
     }
    }).then(res => {
     const { code } = res.data
     if (code === '10119') { //后端接口 返回值
      toast({ title: '登录状态过期,请重新登录' })
      Taro.navigateTo({  //跳转到登录页面 
       url: '/pages/login/index'
      })
     }else{ 
       toast({title:'删除成功!'}) //显示提示框 封装的一个方法 其实到这步,商品就已经删除了,但页面还没有发生变化,所以我们要处理下页面
       let id=item.cartid    
       let data1=this.state.cartdata.filter(item=>{ //过滤下不等于被删除的商品id,将未删除的商品,放到data1中
        return item.cartid!=id
       })
       let data2=this.state.activedata.filter(item=>{ //在选中情况下
        return item.cartid!=id
       })
       this.setState({ //设置下购物车列表数据 
        cartdata:data1,
        activedata:data2
       })
     }
    })
   }else{ //如果没有token值
    toast({ title: '请登录' }) 
    Taro.navigateTo({ //跳转到登录页面
     url: '/pages/login/index'
    })
   }
  }catch(e){
    
  }
 }
 change(item,index,evt) {
  //数量改变
  console.log(evt) 
  //item代表着商品的数据 
  //index,为当前改变的是那个商品的值, 
  //evt为改变后的数值
  try {
   const token = Taro.getStorageSync('token') 
   if (token) { //如果有token值
    if (evt === '0') { //数量为0 我设置的为删除商品,与上面的删除一致,这里我就不再解释了
     request({
      url: '/cart/delete',
      data: {
       token,
       cartid: item.cartid
      }
     }).then(res => {
      const { code } = res.data
      if (code === '10119') {
       toast({ title: '登录状态过期,请重新登录' })
       Taro.navigateTo({
        url: '/pages/login/index'
       })
      }else{
        toast({title:'删除成功!'})
        let id=item.cartid
        let data1=this.state.cartdata.filter(item=>{
         return item.cartid!=id
        })
        let data2=this.state.activedata.filter(item=>{ //在选中情况下
        return item.cartid!=id
       })
        this.setState({
         cartdata:data1,
         activedata:data2
        })

      }
     })
    }else{ //改变的值不为0 ,
     request({
      url: '/cart/update', //更新接口 
      data: {
       token,
       cartid: item.cartid,
       num:evt  //将改变的值直接付给num
      }
     }).then(res => {
      const { code } = res.data
      if (code === '10119') {  //后端验证
       toast({ title: '登录状态过期,请重新登录' })
       Taro.navigateTo({ //跳转到登录页
        url: '/pages/login/index'
       })
      }else{
        toast({title:'更新成功!'})
        item.num=evt //改变下数量
       // var newitem=item
       // var data=this.state.cartdata.map(item=>{
       //  return item.cartid===newitem.cartid ?newitem :item
       // })
       var data=this.state.cartdata //将购物车里边数据赋给data ,因为在react中,状态不能直接改变
       data[index]=item // 将新的对象赋给数组的第index对象
       this.setState({ //设置下
        cartdata:data
       })
      }
     })
    }
   } else {//如果没有token值
    toast({ title: '请登录' })
    Taro.navigateTo({
     url: '/pages/login/index'
    })
   }

  } catch (e) {

  }

 }
}

export default Index
cart/index.scss页面代码
@import "~taro-ui/dist/style/components/card.scss";
@import "~taro-ui/dist/style/components/button.scss";
@import "~taro-ui/dist/style/components/loading.scss";
@import "~taro-ui/dist/style/components/icon.scss";
@import "~taro-ui/dist/style/components/input-number.scss";
utils/index.js代码
const publicurl ='',//接口就不放上去了,因为也不是我的,这里就放接口前的公共网址
import Taro from '@tarojs/taro'
export function request(options){
 const {url,data,method}=options
 wx.showLoading({ //显示loading框
  title: '加载中',
 })
 return new Promise((resolve,reject)=>{
  Taro.request({ //数据请求 与小程序类似
   url: publicurl+url,
   data:data || {},
   method:method || 'GET',
   success(res){ 
    //成功
    resolve(res)
   },
   fail(err){
    //失败
    reject(err)
   },
   complete(){
    // complete 接口调用结束的回调函数
    wx.hideLoading(); //隐藏loading框
   }
  })
 })
}

export function toast(options){
  const {title,icon, duration}=options
  Taro.showToast({ 
   title,
   icon: icon || 'none',
   duration:duration || 1000
  })
}

总结

到此这篇关于taro 实现购物车逻辑的实例代码的文章就介绍到这了,更多相关taro 购物车逻辑内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Javascript 相关文章推荐
一个JavaScript继承的实现
Oct 24 Javascript
js获取提交的字符串的字节数
Feb 09 Javascript
网页中返回顶部代码(多种方法)另附注释说明
Apr 24 Javascript
javascript使用call调用微信API
Dec 15 Javascript
基于JavaScript代码实现随机漂浮图片广告
Jan 05 Javascript
JS实现异步上传压缩图片
Apr 22 Javascript
JavaScript该如何学习 怎样轻松学习JavaScript
Jun 12 Javascript
解决vue中post方式提交数据后台无法接收的问题
Aug 11 Javascript
浅谈React Native 传参的几种方式(小结)
May 21 Javascript
js模拟实现百度搜索
Jun 28 Javascript
vue路由结构可设一层方便动态添加路由操作
Aug 31 Javascript
vue+Element-ui前端实现分页效果
Nov 15 Javascript
Node.js API详解之 V8模块用法实例分析
Jun 05 #Javascript
Vue CLI4 Vue.config.js标准配置(最全注释)
Jun 05 #Javascript
使用Taro实现小程序商城的购物车功能模块的实例代码
Jun 05 #Javascript
Vue路由的模块自动化与统一加载实现
Jun 05 #Javascript
Jquery滑动门/tab切换实现方法完整示例
Jun 05 #jQuery
详解JS函数防抖
Jun 05 #Javascript
Vuex的各个模块封装的实现
Jun 05 #Javascript
You might like
php下过滤HTML代码的函数
2007/12/10 PHP
PHP漏洞全解(详细介绍)
2012/11/13 PHP
ajax取消挂起请求的处理方法
2013/03/18 PHP
百万级别知乎用户数据抓取与分析之PHP开发
2015/09/28 PHP
yii去掉必填项中星号的方法
2015/12/28 PHP
用Greasemonkey 脚本收藏网站会员信息到本地
2009/10/26 Javascript
基于jQuery的仿flash的广告轮播
2010/11/05 Javascript
js内置对象 学习笔记
2011/08/01 Javascript
js作用域及作用域链概念理解及使用
2013/04/15 Javascript
JS控制文本框textarea输入字数限制的方法
2013/06/17 Javascript
wap手机图片滑动切换特效无css3元素js脚本编写
2014/07/28 Javascript
浅谈Javascript中深复制
2014/12/01 Javascript
node.js中的http.request.end方法使用说明
2014/12/10 Javascript
node.js中的fs.realpathSync方法使用说明
2014/12/16 Javascript
Underscore.js常用方法总结
2015/02/28 Javascript
node.js中格式化数字增加千位符的几种方法
2015/07/03 Javascript
Node.js中路径处理模块path详解
2016/11/14 Javascript
bootstrap vue.js实现tab效果
2017/02/07 Javascript
HTML的select控件美化
2017/03/27 Javascript
微信小程序实现tab切换效果
2017/11/21 Javascript
详解Angular5路由传值方式及其相关问题
2018/04/28 Javascript
说说如何使用Vuex进行状态管理(小结)
2019/04/14 Javascript
H5+css3+js搭建带验证码的登录页面
2020/10/11 Javascript
详解vue3中组件的非兼容变更
2021/03/03 Vue.js
python网络爬虫采集联想词示例
2014/02/11 Python
Python编程之基于概率论的分类方法:朴素贝叶斯
2017/11/11 Python
python输出100以内的质数与合数实例代码
2018/07/08 Python
Python类和对象的定义与实际应用案例分析
2018/12/27 Python
pytorch进行上采样的种类实例
2020/02/18 Python
借助HTML5 Canvas来绘制三角形和矩形等多边形的方法
2016/03/14 HTML / CSS
英国异国风情旅游网站:Travel Talk Tours(团体旅游、探险旅游、帆船假期)
2018/07/26 全球购物
餐饮业的创业计划书范文
2013/12/26 职场文书
面试后的感谢信范文
2014/02/01 职场文书
2015年党总支工作总结
2015/05/25 职场文书
赡养老人协议书范本
2015/08/06 职场文书
MySQL学习必备条件查询数据
2022/03/25 MySQL