taro 實(shí)現(xiàn)購(gòu)物車邏輯的實(shí)例代碼
taro 實(shí)現(xiàn)購(gòu)物車邏輯
效果

taro是什么?
Taro 是一套遵循 React 語(yǔ)法規(guī)范的 多端開(kāi)發(fā) 解決方案。
- 現(xiàn)如今市面上端的形態(tài)多種多樣,Web、React-Native、微信小程序等各種端大行其道,當(dāng)業(yè)務(wù)要求同時(shí)在不同的端都要求有所表現(xiàn)的時(shí)候,針對(duì)不同的端去編寫(xiě)多套代碼的成本顯然非常高,這時(shí)候只編寫(xiě)一套代碼就能夠適配到多端的能力就顯得極為需要。
- 使用 Taro,我們可以只書(shū)寫(xiě)一套代碼,再通過(guò) Taro 的編譯工具,將源代碼分別編譯出可以在不同端(微信/百度/支付寶/字節(jié)跳動(dòng)/QQ/京東小程序、快應(yīng)用、H5、React-Native 等)運(yùn)行的代碼。本代碼是基于Taro UI 開(kāi)發(fā)的,雖然是基于 taro框架開(kāi)發(fā)的,但購(gòu)物車的整體邏輯與微信小程序邏輯是基本一樣的
- Taro UI是一款基于 Taro 框架開(kāi)發(fā)的多端 UI 組件庫(kù)
需要安裝taro ui
$ npm install taro-ui
cart/index.jsx頁(yè)面代碼
import Taro, { Component } from '@tarojs/taro'
import { View, Checkbox, CheckboxGroup } from '@tarojs/components'
//用到了taro的三個(gè)組件
//想了解可以去查看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: '', //購(gòu)物車為空時(shí)顯示的信息
cartdata: [], //購(gòu)物車的數(shù)據(jù)列表
isactive: false, //全選按鈕是否選中
check:false, //單個(gè)商品購(gòu)物車是否被選中
totalnum:0, //總數(shù)量
totalprice:0, //總價(jià)格
activedata:[] //復(fù)選框選中的數(shù)據(jù)列表
}
}
componentDidShow () {
//獲取購(gòu)物車數(shù)據(jù)
try {
const token = Taro.getStorageSync('token') //這兩個(gè)數(shù)據(jù)是我在登錄頁(yè)面,登錄時(shí)添加到本地的token和用戶id
const userid = Taro.getStorageSync('userid')
if (token) { //如果登錄了
const usrename = Taro.getStorageSync('username') //同樣登錄時(shí)添加到本地的用戶名
Taro.setNavigationBarTitle({ //改變導(dǎo)航欄的標(biāo)題
title: usrename + '---購(gòu)物車'
})
request({ //這里的request是封裝后的方法
url: '/cart', //接口
data: { //需要傳遞的數(shù)據(jù)
token,
userid
}
}).then(res => {
console.log(res.data)
const { code } = res.data
if (code === '10119') { //后端返回的值 ,判斷狀態(tài)
toast({ title: '登錄已經(jīng)過(guò)期,請(qǐng)從新登錄' })
Taro.navigateTo({ //跳轉(zhuǎn)到登錄頁(yè)
url: '/pages/login/index'
})
} else if (code === '10012') {
this.setState({
message: '購(gòu)物車空空如也'
})
} else {
//因?yàn)閠aro是基于react的,在react中,狀態(tài)不能直接改變,要用this.setState
this.setState({ //登錄成功,購(gòu)物車有數(shù)據(jù)時(shí),將購(gòu)物車的列表數(shù)據(jù)添加到購(gòu)物車數(shù)據(jù)中
cartdata: res.data.data
})
}
})
} else { //如果沒(méi)登錄
toast({ title: '請(qǐng)登錄' })
Taro.navigateTo({ //跳轉(zhuǎn)到登錄頁(yè)面
url: '/pages/login/index'
})
}
} catch (e) {
}
}
componentDidUpdate(){
//計(jì)算總數(shù)量,總價(jià)格
let num=0;
let price=0;
if(this.state.activedata.length!=0){ //如果選中的數(shù)組長(zhǎng)度不為0時(shí),就是有商品被選中了
this.state.activedata.map((item)=>{ //map遍歷數(shù)組
num+= +item.num //將數(shù)量相加 + 號(hào)為一元運(yùn)算符,將字符串類型轉(zhuǎn)換為數(shù)值類型
price+=item.num*item.price //求價(jià)格
})
this.setState({ //設(shè)置值
totalnum:num,
totalprice:price
})
}else{ //如果沒(méi)有商品被選中
this.setState({
totalnum:0,
totalprice:0
})
}
}
render() {
return ( //結(jié)構(gòu)開(kāi)始
<View>{
this.state.message.length === 0 ? null : //如果 message不為空的話,就代表著購(gòu)物車沒(méi)有數(shù)據(jù),所以顯示購(gòu)物車空空如也,去選購(gòu),如果為空,代表著購(gòu)物車有數(shù)據(jù),不顯示
<View onClick={() => { //點(diǎn)擊事件 去主頁(yè)選購(gòu)商品
Taro.switchTab({
url: '/pages/home/index'
})
}}> {this.state.message}去選購(gòu)</View>
}
<Checkbox checked={this.state.isactive} onClick={()=>{ //全選按鈕 check代表著按鈕是否選中 因?yàn)閠aro中的checkbox的onchange方法,不支持小程序,所以沒(méi)辦法,只能用 onClick方法
let active=!this.state.isactive //實(shí)現(xiàn)點(diǎn)擊選中狀態(tài)取反
this.setState({
isactive:active
})
if(active===true){ //如果全選,就代表著 購(gòu)物車的所有商品都被選中,所以,將購(gòu)物車列表數(shù)據(jù)全給選中的數(shù)組,將單個(gè)商品的狀態(tài)全部設(shè)為選中
this.setState({
check:true,
activedata:this.state.cartdata
})
}else{//否則,選中商品數(shù)組為空,將單個(gè)商品的狀態(tài)全部設(shè)為未選中
this.setState({
check:false,
activedata:[]
})
}
}}>全選</Checkbox>
<CheckboxGroup onChange={(evt)=>{ //復(fù)選框組,<CheckboxGroup/>中選中項(xiàng)發(fā)生改變是觸發(fā) change 事件,detail = value:[選中的 Checkbox 的 value 的數(shù)組]
const {detail:{value}}=evt
if(value.length===this.state.cartdata.length){ //選中的數(shù)組的長(zhǎng)度如果等于購(gòu)物車列表的長(zhǎng)度是全選
this.setState({
isactive:true, //全選按鈕被選中
activedata:this.state.cartdata //選中商品數(shù)組為購(gòu)物車的列表數(shù)組
})
}else{ //否則未全選
var i;
var data=[];
for ( i in value){ //因?yàn)関alue數(shù)組里的值為選中的checkbox的value的值,我設(shè)置的為cartid
data.push(...(this.state.cartdata.filter(item=>{ //過(guò)濾下購(gòu)物車的列表數(shù)據(jù),將cartid相等的對(duì)象取出來(lái),放進(jìn)data數(shù)組中,...是展開(kāi)運(yùn)算符,加他是因?yàn)樵诳刂婆_(tái)打印的時(shí)候發(fā)現(xiàn),每個(gè)對(duì)象外面都加了一個(gè)【】,沒(méi)辦法,這里應(yīng)該是有簡(jiǎn)單的寫(xiě)法的,但因?yàn)楫?dāng)時(shí)累了,也沒(méi)有細(xì)想,就只能寫(xiě)成這樣了,
return item.cartid==value[i]
})))
}
console.log(data,this.state.cartdata)
this.setState({
isactive:false,//全選按鈕未被選中
activedata:data //設(shè)置選中商品的數(shù)組
//至此,計(jì)算總數(shù)量,總價(jià)格、全選、單選的邏輯就全完成了,至于為什么寫(xiě)成這樣,是因?yàn)閠aro是基于react的標(biāo)準(zhǔn)的,沒(méi)有計(jì)算屬性,沒(méi)有雙向綁定
})
}
}}>
{
this.state.cartdata.map((item, index) => //循環(huán)顯示購(gòu)物車數(shù)據(jù)
<AtCard
title={item.proname}
thumb={item.proimg}
extra={'$'+item.price}
key={item.proid}
>
<View><Checkbox value={item.cartid} checked={this.state.check}></Checkbox>
{/* 每個(gè)商品前的復(fù)選框 */}
<AtInputNumber //數(shù)量加減
min={0}
max={10}
step={1}
value={item.num} //之間的值
onChange={this.change.bind(this, item,index)} //onchange輸入框值改變時(shí)觸發(fā)的事件,開(kāi)發(fā)者需要通過(guò) onChange 事件來(lái)更新 value 值變化,onChange 函數(shù)必填
/>
<AtButton type='primary' size='small' onClick={this.del.bind(this,item)}>刪除</AtButton>
{/* 刪除按鈕 */}
</View>
</AtCard>
)
}
</CheckboxGroup>
<View>總數(shù)量:{this.state.totalnum}</View>
<View>總價(jià)格:{this.state.totalprice}</View>
</View>
)
}
del(item){ //刪除方法
//item代表著商品的數(shù)據(jù)
try{
const token = Taro.getStorageSync('token')
if(token){ //如果有token值
request({ //數(shù)據(jù)請(qǐng)求 刪除接口
url: '/cart/delete',
data: {
token,
cartid: item.cartid
}
}).then(res => {
const { code } = res.data
if (code === '10119') { //后端接口 返回值
toast({ title: '登錄狀態(tài)過(guò)期,請(qǐng)重新登錄' })
Taro.navigateTo({ //跳轉(zhuǎn)到登錄頁(yè)面
url: '/pages/login/index'
})
}else{
toast({title:'刪除成功!'}) //顯示提示框 封裝的一個(gè)方法 其實(shí)到這步,商品就已經(jīng)刪除了,但頁(yè)面還沒(méi)有發(fā)生變化,所以我們要處理下頁(yè)面
let id=item.cartid
let data1=this.state.cartdata.filter(item=>{ //過(guò)濾下不等于被刪除的商品id,將未刪除的商品,放到data1中
return item.cartid!=id
})
let data2=this.state.activedata.filter(item=>{ //在選中情況下
return item.cartid!=id
})
this.setState({ //設(shè)置下購(gòu)物車列表數(shù)據(jù)
cartdata:data1,
activedata:data2
})
}
})
}else{ //如果沒(méi)有token值
toast({ title: '請(qǐng)登錄' })
Taro.navigateTo({ //跳轉(zhuǎn)到登錄頁(yè)面
url: '/pages/login/index'
})
}
}catch(e){
}
}
change(item,index,evt) {
//數(shù)量改變
console.log(evt)
//item代表著商品的數(shù)據(jù)
//index,為當(dāng)前改變的是那個(gè)商品的值,
//evt為改變后的數(shù)值
try {
const token = Taro.getStorageSync('token')
if (token) { //如果有token值
if (evt === '0') { //數(shù)量為0 我設(shè)置的為刪除商品,與上面的刪除一致,這里我就不再解釋了
request({
url: '/cart/delete',
data: {
token,
cartid: item.cartid
}
}).then(res => {
const { code } = res.data
if (code === '10119') {
toast({ title: '登錄狀態(tài)過(guò)期,請(qǐng)重新登錄' })
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') { //后端驗(yàn)證
toast({ title: '登錄狀態(tài)過(guò)期,請(qǐng)重新登錄' })
Taro.navigateTo({ //跳轉(zhuǎn)到登錄頁(yè)
url: '/pages/login/index'
})
}else{
toast({title:'更新成功!'})
item.num=evt //改變下數(shù)量
// var newitem=item
// var data=this.state.cartdata.map(item=>{
// return item.cartid===newitem.cartid ?newitem :item
// })
var data=this.state.cartdata //將購(gòu)物車?yán)镞厰?shù)據(jù)賦給data ,因?yàn)樵趓eact中,狀態(tài)不能直接改變
data[index]=item // 將新的對(duì)象賦給數(shù)組的第index對(duì)象
this.setState({ //設(shè)置下
cartdata:data
})
}
})
}
} else {//如果沒(méi)有token值
toast({ title: '請(qǐng)登錄' })
Taro.navigateTo({
url: '/pages/login/index'
})
}
} catch (e) {
}
}
}
export default Index
cart/index.scss頁(yè)面代碼 @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 ='',//接口就不放上去了,因?yàn)橐膊皇俏业模@里就放接口前的公共網(wǎng)址
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({ //數(shù)據(jù)請(qǐng)求 與小程序類似
url: publicurl+url,
data:data || {},
method:method || 'GET',
success(res){
//成功
resolve(res)
},
fail(err){
//失敗
reject(err)
},
complete(){
// complete 接口調(diào)用結(jié)束的回調(diào)函數(shù)
wx.hideLoading(); //隱藏loading框
}
})
})
}
export function toast(options){
const {title,icon, duration}=options
Taro.showToast({
title,
icon: icon || 'none',
duration:duration || 1000
})
}
總結(jié)
到此這篇關(guān)于taro 實(shí)現(xiàn)購(gòu)物車邏輯的實(shí)例代碼的文章就介紹到這了,更多相關(guān)taro 購(gòu)物車邏輯內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
鼠標(biāo)拖拽移動(dòng)子窗體的JS實(shí)現(xiàn)
這篇文章主要介紹了鼠標(biāo)拖拽移動(dòng)子窗體的JS實(shí)現(xiàn),需要的朋友可以參考下2014-02-02
詳解springmvc 接收json對(duì)象的兩種方式
本篇文章主要介紹了springmvc 接收json對(duì)象的兩種方式,具有一定的參考價(jià)值,有需要的可以了解一下。2016-12-12
ie與firefox下的event使用說(shuō)明與詳細(xì)區(qū)別
event是ie自帶的一個(gè)對(duì)象,而ff中不存在該對(duì)象,只能通過(guò)傳遞參數(shù)(并且惟一)的方式來(lái)實(shí)現(xiàn)event.2009-10-10
easyui combogrid實(shí)現(xiàn)本地模糊搜索過(guò)濾多列
本篇文章主要介紹了easyui combogrid實(shí)現(xiàn)本地模糊搜索過(guò)濾多列,非常具有實(shí)用價(jià)值,需要的朋友可以參考下2017-05-05
淺析jsopn跨域請(qǐng)求原理及cors(跨域資源共享)的完美解決方法
由于同源策略的緣故,ajax不能向不同域的網(wǎng)站發(fā)出請(qǐng)求。接下來(lái)通過(guò)本文給大家介紹jsopn跨域請(qǐng)求原理及cors(跨域資源共享)的完美解決方法,需要的朋友可以參考下2017-02-02
快速實(shí)現(xiàn)JS圖片懶加載(可視區(qū)域加載)示例代碼
目前很多網(wǎng)站,在圖片加載時(shí)均采用了一種名為懶加載的方式,具體表現(xiàn)為,當(dāng)頁(yè)面被請(qǐng)求時(shí),只加載可視區(qū)域的圖片,其它部分的圖片則不加載,只有這些圖片出現(xiàn)在可視區(qū)域時(shí)才會(huì)動(dòng)態(tài)加載這些圖片,下面本文就介紹了JS圖片懶加載(可視區(qū)域加載)的實(shí)現(xiàn)方法,一起來(lái)看看吧。2017-01-01

