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 相关文章推荐
JS遮罩层效果 兼容ie firefox jQuery遮罩层
Jul 26 Javascript
js限制textarea每行输入字符串长度的代码
Oct 31 Javascript
Node.js模拟浏览器文件上传示例
Mar 26 Javascript
Javascript中的apply()方法浅析
Mar 15 Javascript
jQuery检测返回值的数据类型
Jul 13 Javascript
理解JavaScript中worker事件api
Dec 25 Javascript
jqueryMobile使用示例分享
Jan 12 Javascript
JS拖拽组件学习使用
Jan 19 Javascript
jQuery导航条固定定位效果实例代码
May 26 jQuery
react高阶组件经典应用之权限控制详解
Sep 07 Javascript
React手稿之 React-Saga的详解
Nov 12 Javascript
JavaScript对象属性操作实例解析
Feb 04 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 session安全问题分析
2011/06/24 PHP
Nginx下配置codeigniter框架方法
2015/04/07 PHP
php查询操作实现投票功能
2016/05/09 PHP
jQuery使用手册之三 CSS操作
2007/03/24 Javascript
超级24小时弹窗代码 24小时退出弹窗代码 100%弹窗代码(IE only)
2010/06/11 Javascript
js bind 函数 使用闭包保存执行上下文
2011/12/26 Javascript
使用js简单实现了tree树菜单
2013/11/20 Javascript
JavaScript中的6种运算符总结
2014/10/16 Javascript
javascript事件绑定学习要点
2016/03/09 Javascript
js编写一个简单的产品放大效果代码
2016/06/27 Javascript
基于JS设计12306登录页面
2016/12/28 Javascript
vue-router 导航钩子的具体使用方法
2017/08/31 Javascript
vue给input file绑定函数获取当前上传的对象完美实现方法
2017/12/15 Javascript
vue侧边栏动态生成下级菜单的方法
2018/09/07 Javascript
vue form check 表单验证的实现代码
2018/12/09 Javascript
解决Layui当中的导航条动态添加后渲染失败的问题
2019/09/25 Javascript
移动端JS实现拖拽两种方法解析
2020/10/12 Javascript
Python实现监控程序执行时间并将其写入日志的方法
2015/06/30 Python
Python判断一个list中是否包含另一个list全部元素的方法分析
2018/12/24 Python
Python3.6.2调用ffmpeg的方法
2019/01/10 Python
使用python Telnet远程登录执行程序的方法
2019/01/26 Python
使用python快速在局域网内搭建http传输文件服务的方法
2019/11/14 Python
怎样在程序里获得一个空指针
2015/01/24 面试题
学校庆元旦歌咏比赛主持词
2014/03/18 职场文书
2014年外贸业务员工作总结
2014/12/11 职场文书
乌镇导游词
2015/02/02 职场文书
大班下学期个人总结
2015/02/13 职场文书
班级联欢会主持词
2015/07/03 职场文书
你会写请假条吗?
2019/06/26 职场文书
导游词之峨眉山
2019/12/16 职场文书
一文搞懂如何实现Go 超时控制
2021/03/30 Python
Redis安装启动及常见数据类型
2021/04/14 Redis
Vue中foreach数组与js中遍历数组的写法说明
2021/06/05 Vue.js
node.js如何自定义实现一个EventEmitter
2021/07/16 Javascript
vue-cil之axios的二次封装与proxy反向代理使用说明
2022/04/07 Vue.js
Spring Boot项目如何优雅实现Excel导入与导出功能
2022/06/10 Java/Android