taro realizes shopping cart logic

taro realizes shopping cart logic

  • What is taro?
  • Taro is a multi terminal development solution that follows the React syntax specification.
    Nowadays, there are various forms on the market, such as Web, react native, wechat applet and so on. When the business requirements are expressed in different ends at the same time, the cost of writing multiple sets of code for different ends is obviously very high. At this time, the ability to write only one set of code to adapt to multiple ends is extremely needed.
    Using Taro, we can only write a set of code, and then compile the source code separately through the Taro compiler tool to run the code at different ends (WeChat / Baidu / Alipay / byte beat /QQ/ Jingdong applet, fast application, H5, React-Native, etc.).
  • This code is developed based on Taro UI. Although it is developed based on taro framework, the overall logic of shopping cart is basically the same as that of wechat applet
    Taro UI is a multi terminal UI component library based on taro framework
    taro ui needs to be installed
    $ npm install taro-ui

Official taro documents
Official taroUI documentation

cart/index.jsx Page code
import Taro, { Component } from '@tarojs/taro'
import { View, Checkbox, CheckboxGroup } from '@tarojs/components' 
//Three components of taro are used
//Want to know the official documents of 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: '', //Information displayed when shopping cart is empty
      cartdata: [],  //Data list of shopping cart
      isactive: false,  //Select all button or not
      check:false, //Whether the single item shopping cart is selected
      totalnum:0, //Total quantity
      totalprice:0, //Total price
      activedata:[]  //Check box selected data list
    }

  }
  componentDidShow () {
    //Get cart data
    try {
      const token = Taro.getStorageSync('token')  //These two data are the token and user id that I added to the local login page
      const userid = Taro.getStorageSync('userid')
      if (token) {  //If you log in
        const usrename = Taro.getStorageSync('username') //The same user name added to the local when logging in
        Taro.setNavigationBarTitle({  //Change the title of the navigation bar
          title: usrename + '---Shopping Cart'
        })
        request({ //The request here is the method after encapsulation
          url: '/cart',  //Interface
          data: { //Data to be transferred
            token,
            userid
          }
        }).then(res => {  
          console.log(res.data)
          const { code } = res.data  
          if (code === '10119') {  //Value returned by back end, judge status
            toast({ title: 'Login has expired, please login from New' })
            Taro.navigateTo({   //Jump to landing page
              url: '/pages/login/index'
            })
          } else if (code === '10012') {  
            this.setState({
              message: 'Shopping cart is empty'
            })
          } else {
          //Because taro is based on react. In react, the state cannot be changed directly. Use this.setState
            this.setState({  //Login succeeded. When the shopping cart has data, add the list data of the shopping cart to the shopping cart data 
              cartdata: res.data.data
            })
          }
        })
      } else {  //If you don't log in
        toast({ title: 'Please login' })
        Taro.navigateTo({ //Jump to login page
          url: '/pages/login/index'
        })
      }

    } catch (e) {

    }
  }
  componentDidUpdate(){
    //Calculate total quantity, total price
    let num=0;
    let price=0;
    if(this.state.activedata.length!=0){  //If the length of the selected array is not 0, a product is selected
      this.state.activedata.map((item)=>{  //map traversal array
        num+= +item.num   //Add quantity + sign as unary operator, convert string type to numeric type
        price+=item.num*item.price   //Asking price
      }) 
      this.setState({  //Set value
        totalnum:num,
        totalprice:price
      })
    }else{  //If no item is selected
      this.setState({
        totalnum:0,
        totalprice:0
      })
    }
   
  }
  render() {
    return ( //Structure start
      <View>{
        this.state.message.length === 0 ? null :  //If the message is not empty, it means that there is no data in the shopping cart, so the display shows that the shopping cart is empty. Go shopping. If it is empty, it means that there is data in the shopping cart, not displayed
          <View onClick={() => { //Click the event to go to the home page to buy goods
            Taro.switchTab({
              url: '/pages/home/index'
            })
          }}> {this.state.message}Go shopping</View>
      }
        <Checkbox checked={this.state.isactive} onClick={()=>{  //Select all button check indicates whether the button is selected. Because the onchange method of the checkbox in taro does not support applets, there is no way but to use onClick method
          let active=!this.state.isactive     //Reverse the click selected status
          this.setState({   
            isactive:active
          })
          if(active===true){  //If all items are selected, all items in the shopping cart will be selected. Therefore, the data in the shopping cart list will be given to the selected array, and the status of individual items will be set to selected
            this.setState({
              check:true,
              activedata:this.state.cartdata
            })
          }else{//Otherwise, the selected item array is empty, and the status of all individual items is set to unchecked
            this.setState({
              check:false,
              activedata:[]
            })
          }
        }}>All election</Checkbox>

        <CheckboxGroup   onChange={(evt)=>{  //Check box group, if the selected item in < checkboxgroup / > changes, the change event will be triggered, detail = value: [array of value of the selected Checkbox]
          const {detail:{value}}=evt  
          if(value.length===this.state.cartdata.length){ //If the length of the selected array is equal to the length of the shopping cart list, select all
            this.setState({   
              isactive:true,    //Select all button selected
              activedata:this.state.cartdata   //The selected item array is the list array of shopping cart
            })
          }else{  //Otherwise, not all
            var i;
            var data=[];
            for ( i in value){   //Because the value in the value array is the value of the selected checkbox, I set it to card
              data.push(...(this.state.cartdata.filter(item=>{  //Filter the list data of the shopping cart, take out the objects with the same cartid, and put them into the data array,... Is the expansion operator. When printing on the console, it is found that a [] is added to each object. There is no way. There should be a simple way to write here, but because I was tired at that time and didn't think about it, I can only write like this,
                return item.cartid==value[i]
              })))
            }
            console.log(data,this.state.cartdata)
            this.setState({
              isactive:false,//Select all button not selected
              activedata:data //Set the array of selected items
              //At this point, the logic of calculating the total quantity, total price, select all, and single choice is all completed. As for why it is written like this, it is because the taro is based on the react standard, there is no calculation attribute, and there is no two-way binding
            })
          }
        }}>
          {
            this.state.cartdata.map((item, index) =>  //Cycle shopping cart data
              <AtCard
                title={item.proname}
                thumb={item.proimg}
                extra={'$'+item.price}
                key={item.proid}

              >
                <View><Checkbox value={item.cartid} checked={this.state.check}></Checkbox> //Check box before each item
                  <AtInputNumber  //Quantity addition and subtraction
                    min={0}
                    max={10}
                    step={1}
                    value={item.num} //Value between
                    onChange={this.change.bind(this, item,index)}  //The event triggered when the value of the onChange input box changes. The developer needs to update the value change through the onChange event. The onChange function is required
                  />
                  <AtButton type='primary' size='small' onClick={this.del.bind(this,item)}>delete</AtButton> //Delete button
                </View>

              </AtCard>
            )
          }
        </CheckboxGroup>
        <View>Total quantity:{this.state.totalnum}</View>
        <View>Total price:{this.state.totalprice}</View>
      </View>
    )
  }
  del(item){ //Deletion method
  //item represents product data  
    try{
      const token = Taro.getStorageSync('token')
      if(token){ //If there is a token value
        request({ //Data request delete interface
          url: '/cart/delete',
          data: {
            token,
            cartid: item.cartid
          }
        }).then(res => {
          const { code } = res.data
          if (code === '10119') {  //Back end interface return value
            toast({ title: 'Login status expired, please login again' })
            Taro.navigateTo({   //Jump to login page  
              url: '/pages/login/index'
            })
          }else{ 
             toast({title:'Delete successful!'})  //One of the ways to display the prompt box is to delete the product, but the page hasn't changed, so we need to deal with the next page
             let id=item.cartid       
             let data1=this.state.cartdata.filter(item=>{  //Filter the item id that is not equal to the deleted item, and put the undeleted item into data1
               return item.cartid!=id
             })
             let data2=this.state.activedata.filter(item=>{  //When selected
               return item.cartid!=id
             })
             this.setState({ //Set shopping cart list data 
               cartdata:data1,
               activedata:data2
             })
          }
        })
      }else{ //If there is no token value
        toast({ title: 'Please login' })  
        Taro.navigateTo({  //Jump to login page
          url: '/pages/login/index'
        })
      }
    }catch(e){
        
    }
  }
  change(item,index,evt) {
    //Quantity change
    console.log(evt) 
    //item represents product data  
    //index, for the value of the commodity that is currently changed, 
    //evt is the changed value
    try {
      const token = Taro.getStorageSync('token') 
      if (token) {  //If there is a token value
        if (evt === '0') { //The quantity is 0. I set it to delete goods, which is consistent with the above deletion. I will not explain it here
          request({
            url: '/cart/delete',
            data: {
              token,
              cartid: item.cartid
            }
          }).then(res => {
            const { code } = res.data
            if (code === '10119') {
              toast({ title: 'Login status expired, please login again' })
              Taro.navigateTo({
                url: '/pages/login/index'
              })
            }else{
               toast({title:'Delete successful!'})
               let id=item.cartid
               let data1=this.state.cartdata.filter(item=>{
                 return item.cartid!=id
               })
                let data2=this.state.activedata.filter(item=>{  //When selected
               return item.cartid!=id
             })
               this.setState({
                 cartdata:data1,
                 activedata: data2
               })

            }
          })
        }else{  //The changed value is not 0,
          request({
            url: '/cart/update', //Update interface 
            data: {
              token,
              cartid: item.cartid,
              num:evt   //Pay the changed value directly to num
            }
          }).then(res => {
            const { code } = res.data
            if (code === '10119') {   //Back-end verification
              toast({ title: 'Login status expired, please login again' })
              Taro.navigateTo({  //Jump to landing page
                url: '/pages/login/index'
              })
            }else{
               toast({title:'Update success!'})
               item.num=evt  //Quantity under change
              //  var newitem=item
              //  var data=this.state.cartdata.map(item=>{
              //    return item.cartid===newitem.cartid ?newitem :item
              //  })
              var data=this.state.cartdata  //Assign the data in the shopping cart to data, because in react, the status cannot be changed directly
              data[index]=item  // Assign the new object to the index object of the array
              this.setState({ //Set down
                cartdata:data
              })
            }
          })
        }
      } else {//If there is no token value
        toast({ title: 'Please login' })
        Taro.navigateTo({
          url: '/pages/login/index'
        })
      }

    } catch (e) {

    }

  }
}

export default Index

cart/index.scss Page code
@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 Code
const publicurl =''//The interface will not be put on, because it's not mine either. Here is the public address in front of the interface
import Taro from '@tarojs/taro'
export function request(options){
  const {url,data,method}=options
  wx.showLoading({  //Show loading box
    title: 'Loading',
  })
  return new Promise((resolve,reject)=>{
    Taro.request({  //Data requests are similar to applets
      url: publicurl+url,
      data:data || {},
      method:method || 'GET',
      success(res){ 
        //Success
        resolve(res)
      },
      fail(err){
        //fail
        reject(err)
      },
      complete(){
        // The callback function at the end of the complete interface call
        wx.hideLoading(); //Hide loading box
      }
    })
  })
}

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

In this special period, we should be more down-to-earth, to learn, to improve and to "fight against the enemy"

37 original articles published, 19 praised, 3252 visited
Private letter follow

Tags: React npm Attribute

Posted on Sat, 22 Feb 2020 04:35:58 -0500 by clown[NOR]