1. 程式人生 > 程式設計 >taro 實現購物車邏輯的例項程式碼

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 購物車邏輯內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!