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 相关文章推荐
HTA版JSMin(省略修饰语若干)基于javascript语言编写
Dec 24 Javascript
动态标签 悬停效果 延迟加载示例代码
Nov 21 Javascript
解决jquery插件冲突的问题
Jan 23 Javascript
JS判断字符串长度的5个方法(区分中文和英文)
Mar 18 Javascript
JavaScript实现俄罗斯方块游戏过程分析及源码分享
Mar 23 Javascript
JavaScript获取页面中超链接数量的方法
Nov 09 Javascript
轻松使用jQuery双向select控件Bootstrap Dual Listbox
Dec 13 Javascript
详解JavaScript数组和字符串中去除重复值的方法
Mar 07 Javascript
纯前端JavaScript实现Excel IO案例分享
Aug 26 Javascript
WebView启动支付宝客户端支付失败的问题小结
Jan 11 Javascript
jQuery中 DOM节点操作方法大全
Oct 12 jQuery
Node.js 在本地生成日志文件的方法
Feb 07 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使之能同时支持GIF和JPEG
2006/10/09 PHP
PHP判断图片格式的七种方法小结
2013/06/03 PHP
神盾加密解密教程(三)PHP 神盾解密工具
2014/06/08 PHP
PHP获取数组最大值下标的方法
2015/05/12 PHP
php实现数组中索引关联数据转换成json对象的方法
2015/07/08 PHP
php正则表达式获取内容所有链接
2015/07/24 PHP
完美利用Yii2微信后台开发的系列总结
2016/07/18 PHP
php及codeigniter使用session-cookie的方法(详解)
2017/04/06 PHP
php中钩子(hook)的原理与简单应用demo示例
2019/09/03 PHP
javascript 强制刷新页面的实现代码
2009/12/13 Javascript
html超链接打开窗口大小的方法
2013/03/05 Javascript
javascript感应鼠标图片透明度显示的方法
2015/02/24 Javascript
jQuery动画显示和隐藏效果实例演示(附demo源码下载)
2015/12/31 Javascript
Javascript学习之谈谈JS的全局变量跟局部变量(推荐)
2016/08/28 Javascript
vue2实现移动端上传、预览、压缩图片解决拍照旋转问题
2017/04/13 Javascript
uploader秒传图片到服务器完整代码
2017/04/22 Javascript
从零开始搭建webpack+react开发环境的详细步骤
2018/05/18 Javascript
security.js实现的RSA加密功能示例
2018/06/06 Javascript
JS闭包原理与应用经典示例
2018/12/20 Javascript
Javascript模块化机制实现原理详解
2020/04/02 Javascript
Vue前端判断数据对象是否为空的实例
2020/09/02 Javascript
[02:12]2015国际邀请赛 SHOWOPEN
2015/08/05 DOTA
Python内建函数之raw_input()与input()代码解析
2017/10/26 Python
ubuntu中配置pyqt4环境教程
2017/12/27 Python
Python 12306抢火车票脚本 Python京东抢手机脚本
2018/02/06 Python
Python 网络爬虫--关于简单的模拟登录实例讲解
2018/06/01 Python
Python3环境安装Scrapy爬虫框架过程及常见错误
2019/07/12 Python
tensorflow下的图片标准化函数per_image_standardization用法
2020/06/30 Python
西尔斯百货官网:Sears
2016/09/06 全球购物
Otticanet意大利:最顶尖的世界名牌眼镜, 能得到打折季的价格
2019/03/10 全球购物
应届护士推荐信
2013/11/16 职场文书
大学生演讲稿范文
2014/01/11 职场文书
土地转让协议书
2014/09/27 职场文书
小学感恩节活动策划方案
2014/10/06 职场文书
单位领导婚礼致辞
2015/07/28 职场文书
2016年春季运动会广播稿
2015/08/19 职场文书