微信小程序購物車、父子組件傳值及calc的注意事項(xiàng)總結(jié)
前言
在做微信小程序時(shí),覺得小組里對(duì)購物車的實(shí)現(xiàn)不是很完美,就自己嘗試的寫了下,然后用到了父子組件傳值,父子組件傳值的話,和vue框架上是非常相似的,以及calc這個(gè)css函數(shù),calc有個(gè)注意點(diǎn),自己不怎么用,一時(shí)間有差點(diǎn)忘了,這里記錄下
下面話不多說了,來一起看看詳細(xì)的介紹吧
1.效果圖
2.子組件實(shí)現(xiàn)
要實(shí)現(xiàn)圖中刪除的效果,使用組件的形式更好做點(diǎn),我當(dāng)時(shí)本想直接在pages里實(shí)現(xiàn),不過結(jié)果就是,滑動(dòng)時(shí),所有的商品都顯示了刪除按鈕,除非用數(shù)組將每個(gè)商品要移動(dòng)的距離存儲(chǔ)起來,不過這樣的話就很麻煩,所以我也是用組件來實(shí)現(xiàn)的
關(guān)于微信組件,可以直接點(diǎn)擊鏈接訪問官網(wǎng)查看自定義組件
子組件index.wxml
<view class="commodityItem" bindtouchstart="handleTouchStart" bindtouchmove="handleTouchMove" style="transform:translateX({{-rightSpace}}px)"> <view class="selectedBtn" bindtap="handleSelect" data-is-selected="{{commodity.isselected}}"> <view class="noSelected" wx:if="{{commodity.isselected==0}}"></view> <image class="selectedImg" wx:else src="/images/selected.png"></image> </view> <view class="commodityInfo"> <view class="commodityImg"> <image src="{{commodity.image}}"></image> </view> <view class="commodityTitle"> <view class="title">{{commodity.title}}</view> <view class="standard">規(guī)格:{{commodity.standard?commodity.standard:'無'}}</view> <view class="count"> <view class="price">¥{{commodity.price}}</view> <view class="commodityNum"> <i-input-number value="{{selectedNum}}" min="1" max="{{commodity.stock}}" bindchange="numChange" /> </view> </view> </view> </view> <view class="deleteBtn"> <image class="deleteImg" src="/images/delete.png"></image> <text class="deleteText">刪除</text> </view> </view>
子組件index.wxss
/* 商品 */ .commodityItem{ display: flex; position: relative; padding: 10rpx 24rpx 20rpx 30rpx; box-sizing: border-box; background: #fff; transition: all .5s; } /* 選擇按鈕 */ .selectedBtn{ display: flex; align-items: center; width: 80rpx; } .noSelected{ width: 46rpx; height: 46rpx; border-radius: 50%; border: 1px solid #ef5225; } .selectedBtn .selectedImg{ width: 50rpx; height: 50rpx; } /* 商品信息 */ .commodityInfo{ display: flex; width: calc(100% - 80rpx); } .commodityImg{ margin-right: 18rpx; width: 220rpx; height: 220rpx; } .commodityImg image{ width: 100%; height: 100%; vertical-align: middle; } /* 商品title */ .commodityTitle{ width: calc(100% - 220rpx); } .title{ display: -webkit-box; width: 100%; height: 70rpx; line-height:35rpx; font-size: 24rpx; font-weight:600; overflow: hidden; -webkit-line-clamp: 2; -webkit-box-orient: vertical; } .standard{ padding-top: 16rpx; width: 100%; height: 90rpx; box-sizing: border-box; } .count{ display: flex; align-items: center; justify-content: space-between; width: 100%; height: 60rpx; } /* 刪除按鈕 */ .deleteBtn{ display: flex; position: absolute; width: 70px; height: 100%; top: 0rpx; right: -70px; flex-direction: column; align-items: center; justify-content: center; background: #ef5225; } .deleteImg{ margin-bottom: 10rpx; width: 50rpx; height: 50rpx; vertical-align: middle; } .deleteText{ color: #fff; }
子組件index.json,這里用了iview中的數(shù)字輸入框
{ "component": true, "usingComponents": { "i-input-number": "/component/iview/input-number/index" } }
子組件index.js
Component({ properties: { commodity: Object, }, data: { touchStart: null, rightSpace: 0, selectedNum: 1, }, methods: { /* 商品是否選中 */ handleSelect() { let selectedNum = this.data.selectedNum; let commodity = this.data.commodity; if(commodity.isselected == 0) { commodity.isselected = 1; } else { commodity.isselected = 0; } this.triggerEvent('handleselect', { commodity, selectedNum}) }, /* 處理觸摸滑動(dòng)開始 */ handleTouchStart(e) { /* 記錄觸摸滑動(dòng)初始位置 */ let touchStart = e.changedTouches[0].clientX; this.setData({ touchStart }) }, /* 處理觸摸滑動(dòng) */ handleTouchMove(e) { console.log(e) let moveSpace = e.changedTouches[0].clientX; let touchStart = this.data.touchStart; if (touchStart != null) { if (moveSpace - touchStart > 70) { this.setData({ touchStart: null, rightSpace: 0 }) } else if (moveSpace - touchStart < -70) { this.setData({ touchStart: null, rightSpace: 70 }) } } }, numChange(e) { let selectedNum = e.detail.value; let commodity = this.data.commodity; this.setData({ selectedNum }) this.triggerEvent('handleselect', { commodity, selectedNum}) } } })
3.父組件實(shí)現(xiàn)
父組件index.wxml,這里用的是假數(shù)據(jù),所以操作上會(huì)有一些是聯(lián)調(diào)時(shí)不必要的操作
<view class="cart"> <view class="item" wx:for="{{cartList}}" wx:key="{{items.shopid}}" wx:for-item="items"> <view class="storeInfo"> <image class="avatar" src="{{items.logo}}"></image> <view class="storeName">{{items.shopname}}</view> </view> <view class="discount">滿¥100包郵,滿10件包郵</view> <view class="commodity" wx:for="{{items.commodity}}" wx:key="{{item.id}}"> <cart-item commodity="{{item}}" bind:handleselect="handleSelect" /> </view> </view> <view class="count"> <view class="selectAll" bindtap="handleSelectAll"> <view class="noSelected" wx:if="{{!isSelectedAll}}"></view> <image class="selectedImg" wx:else src="/images/selected.png"></image> <text class="selectAllText">全選</text> </view> <view class="countPrice"> <text>合計(jì):</text> <text>¥{{countPrice}}</text> </view> <view class="account"> <text>結(jié)算</text> <text>({{countSelectedNum}})</text> </view> </view> </view>
父組件index.wxss
page{ background: #f8f8f8; } .cart{ padding-bottom: 100rpx; font-size: 26rpx; } .item{ border-bottom: 1px solid #eee; } /* 頭部店鋪信息 */ .storeInfo{ display: flex; padding: 18rpx 0rpx 18rpx 30rpx; background: #fff; box-sizing: border-box; } .storeInfo .avatar{ width: 56rpx; height: 56rpx; border-radius: 50%; vertical-align: middle; } .storeInfo .storeName{ margin-left: 16rpx; line-height: 56rpx; } /* 包郵信息 */ .discount{ padding-left: 30rpx; height:50rpx; line-height: 50rpx; font-size:20rpx; color: #666; box-sizing: border-box; } /* 底部操作 */ .count{ display: flex; position: fixed; padding-left: 30rpx; bottom: 0; left: 0; width: 100%; height: 100rpx; line-height: 100rpx; box-sizing: border-box; color: #232323; background: #eee; } /* 全選 */ .selectAll{ display: flex; padding-right: 20rpx; align-items: center; width: 25%; font-size: 30rpx; } .selectAll .noSelected{ width: 46rpx; height: 46rpx; border-radius: 50%; border: 1px solid #ef5225; } .selectAll .selectedImg{ width: 50rpx; height: 50rpx; } .selectAllText{ margin-left: 18rpx; } .countPrice{ position: absolute; top: 0; right: 270rpx; height: 100%; line-height: 100rpx; text-align: center; font-size: 30rpx; } .countPrice text{ margin-right: 15rpx; } .account{ position: absolute; top: 0; right: 0; width: 270rpx; height: 100%; line-height: 100rpx; text-align: center; font-size: 30rpx; background: #ef5225; color: #fff; } 父組件index.json,引用子組件 { "usingComponents": { "cart-item": "/component/cart/index" } }
父組件index.js
Page({ data: { cartList: [ { shopname: '貓咪小店', logo: '/images/avatar.jpeg', shopid: 11, commodity: [ { id: 1, image:'/images/commodity.jpg', title: '雅詩蘭黛鮮活煥亮紅石榴晚霜50ml 補(bǔ)水保濕 滋潤排濁', standard: '111 + 黑色', price: '100', stock: 10, quantity: 1, isselected: 0, }, { id: 2, image:'/images/avatar7.jpg', title: '雅詩蘭黛鮮活煥亮紅石榴晚霜50ml 補(bǔ)水保濕 滋潤排濁', price: '10', stock: 5, quantity: 1, isselected: 0, } ] }, { shopname: '貓咪小店', logo: '/images/avatar5.jpg', shopid: 450, commodity: [ { id: 3, image:'/images/commodity.jpg', title: '雅詩蘭黛鮮活煥亮紅石榴晚霜50ml 補(bǔ)水保濕 滋潤排濁', price: '90', stock: 10, quantity: 1, isselected: 0, }, { id: 4, image:'/images/avatar7.jpg', title: '雅詩蘭黛鮮活煥亮紅石榴晚霜50ml 補(bǔ)水保濕 滋潤排濁', price: '100', stock: 5, quantity: 1, isselected: 0, }, { id: 5, image:'/images/commodity.jpg', title: '雅詩蘭黛鮮活煥亮紅石榴晚霜50ml 補(bǔ)水保濕 滋潤排濁', standard: '111 + 黑色', price: '100', stock: 2, quantity: 1, isselected: 0, } ] }, { shopname: '貓咪小店', logo: '/images/avatar.jpeg', shopid: 550, commodity: [ { id: 6, image:'/images/avatar8.jpg', title: '雅詩蘭黛鮮活煥亮紅石榴晚霜50ml 補(bǔ)水保濕 滋潤排濁', standard: '111 + 黑色', price: '100', stock: 1, quantity: 1, isselected: 0, } ] }, ], /* 商品是否全選中 */ isSelectedAll: false, /* 已選中商品的價(jià)格 */ countPrice: 0, /* 統(tǒng)計(jì)所有選中的商品數(shù)量 */ countSelectedNum: 0, }, /* 處理商品選中 */ handleSelect(e) { let countPrice = 0; let countSelectedNum = 0; let cartList = this.data.cartList; let length = cartList.length; /* 因?yàn)槭羌贁?shù)據(jù),所以需要循環(huán)查找到對(duì)應(yīng)的數(shù)據(jù)將其替換 */ for(let i = 0; i < length; i++) { for(let j = 0; j < cartList[i].commodity.length; j++) { if (cartList[i].commodity[j].id == e.detail.commodity.id) { cartList[i].commodity[j] = e.detail.commodity; cartList[i].commodity[j].selectedNum = e.detail.selectedNum; } if (cartList[i].commodity[j].isselected == 1) { /* 點(diǎn)擊選中的時(shí)候,計(jì)算價(jià)格,要判斷下設(shè)置的商品選中數(shù)量, * 我這里的是對(duì)點(diǎn)擊了的商品才設(shè)置了選中的數(shù)量,所以需要對(duì)沒有點(diǎn)擊的商品數(shù)量設(shè)置為1,然后就默認(rèn)的加一 */ if (cartList[i].commodity[j].selectedNum != undefined) { countPrice += cartList[i].commodity[j].price * cartList[i].commodity[j].selectedNum; countSelectedNum += cartList[i].commodity[j].selectedNum } else { countPrice += cartList[i].commodity[j].price * 1; countSelectedNum += 1; } } } } /* 對(duì)是否全選中進(jìn)行判斷 */ let isSelectedAll = true; for (let i = 0; i < length; i++) { for (let j = 0; j < cartList[i].commodity.length; j++) { /* 若商品中的isselecetd有為0的就終止循環(huán),直接設(shè)置為未全選 */ if (cartList[i].commodity[j].isselected == 0) { isSelectedAll = false; break; } } } this.setData({ cartList, isSelectedAll, countPrice, countSelectedNum }) }, /* 全選中商品 */ handleSelectAll() { let isSelectedAll = !this.data.isSelectedAll; let cartList = this.data.cartList; let length = cartList.length; let countPrice = 0; let countSelectedNum = 0; /* 遍歷數(shù)據(jù)中的isselected來進(jìn)行全選的操作 */ for(let i = 0; i < length; i++) { for (let j = 0; j < cartList[i].commodity.length; j++) { if(isSelectedAll) { cartList[i].commodity[j].isselected = 1; /* 全選的時(shí)候,計(jì)算價(jià)格,要判斷下設(shè)置的商品選中數(shù)量, * 我這里的是對(duì)點(diǎn)擊了的商品才設(shè)置了選中的數(shù)量,所以需要對(duì)沒有點(diǎn)擊的商品數(shù)量設(shè)置為1,然后就默認(rèn)加一 */ if (cartList[i].commodity[j].selectedNum != undefined) { countPrice += parseInt(cartList[i].commodity[j].price) * cartList[i].commodity[j].selectedNum; countSelectedNum += cartList[i].commodity[j].selectedNum; } else { countPrice += cartList[i].commodity[j].price * 1; countSelectedNum += 1; } } else { cartList[i].commodity[j].isselected = 0; } } } this.setData({ isSelectedAll, cartList, countPrice, countSelectedNum }) }, })
4.父子組件傳值
較常用的都是父組件往子組件傳值,所以子組件往父組件傳值就會(huì)不是很熟悉
我這里的話,是因?yàn)橛玫募贁?shù)據(jù),在點(diǎn)擊商品選中或者不選中時(shí),需要改變商品里的選中屬性,所以用到了子組件往父組件傳值,也包括傳遞選中的商品數(shù)量
子組件往父組件傳值的話,是通過在調(diào)用this.triggerEvent()來實(shí)現(xiàn)的
/* 在父組件中定義方法:bind:handleselect或者也可以直接寫成bindhandleselect*/ <cart-item commodity="{{item}}" bind:handleselect="handleSelect" />
在子組件中調(diào)用
this.triggerEvent('handleselect', { commodity, selectedNum})
這個(gè)this.triggerEvent('handleselect', { commodity, selectedNum })方法中,handleselect的名稱要與父組件中引用子組件時(shí)綁定的方法名稱一樣,后面的對(duì)象就是傳遞的值,也可以直接是以直接量的形式傳遞,然后再父組件中通過e.detail來獲取對(duì)應(yīng)的值
handleSelect(e) { console.log(e.detail) console.log(e.detail.commodity) console.log(e.detail.selectedNum) }
5.calc的注意事項(xiàng)
我以前也遇到過,然后現(xiàn)在再用的時(shí)候,一時(shí)間把這點(diǎn)給忘了,在看到編譯器樣式的時(shí)候,才猛然想起
.user-content{ padding: 10px 0 10px 50px; width: calc(100% - 50px); /* 計(jì)算寬度,'+'或'-'符號(hào)前后有空格 */ height: 18px; }
css中使用calc可以進(jìn)行簡單的運(yùn)算:
單位可以是百分比,px,rem,em等單位
使用"+","-","*","/"運(yùn)算符(使用"+"或者"-"符號(hào)時(shí),符號(hào)前后必須加上空格)
在Firefox瀏覽器上使用要加上-moz前綴
chrome瀏覽器上使用要加上-webkit前綴
(使用"+"或者"-"符號(hào)時(shí),符號(hào)前后必須加上空格)
6.部分想法
其實(shí)在樣式上還是挺快就完成了,就是在計(jì)算商品價(jià)格的時(shí)候,想了挺久
在計(jì)算價(jià)格時(shí),當(dāng)時(shí)就有點(diǎn)蒙圈,總是想著要怎么判斷他是增加數(shù)量還是減少數(shù)量,然后就陷入死循環(huán)的之中。
其實(shí)不用想她是增加還是減少數(shù)量,因?yàn)槟愣际莻鞯氖巧唐返臄?shù)量,而且在計(jì)算時(shí),也是判斷了商品是否選中,所以,直接點(diǎn),計(jì)算價(jià)格乘以數(shù)量就可以了
然后選中的商品數(shù)量的統(tǒng)計(jì)就和計(jì)算價(jià)格的思路是一樣的了
總結(jié)
以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問大家可以留言交流,謝謝大家對(duì)腳本之家的支持。
相關(guān)文章
純JS實(shí)現(xiàn)可用于頁碼更換的飛頁特效示例
這篇文章主要介紹了純JS實(shí)現(xiàn)可用于頁碼更換的飛頁特效,涉及javascript結(jié)合時(shí)間函數(shù)的數(shù)學(xué)運(yùn)算與頁面元素屬性動(dòng)態(tài)修改相關(guān)操作技巧,需要的朋友可以參考下2018-05-05利用JS重寫Cognos右鍵菜單的實(shí)現(xiàn)代碼
我寫了一個(gè)利用JS禁用Cognos右鍵菜單,下面的JS可以實(shí)現(xiàn)重寫Cognos的右鍵菜單。只要將下面的代碼拷到一個(gè)HTML項(xiàng)里即可。2010-04-04ionic實(shí)現(xiàn)帶字的toggle滑動(dòng)組件
這篇文章主要為大家詳細(xì)介紹了ionic實(shí)現(xiàn)帶字的toggle滑動(dòng)組件,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-08-08JavaScript正則表達(dá)式匹配 div style標(biāo)簽
這篇文章主要介紹了JavaScript正則表達(dá)式匹配<div><style>標(biāo)簽 的相關(guān)資料,需要的朋友可以參考下2016-03-03JavaScript實(shí)現(xiàn)顯示函數(shù)調(diào)用堆棧的方法
這篇文章主要介紹了JavaScript實(shí)現(xiàn)顯示函數(shù)調(diào)用堆棧的方法,實(shí)例分析了JavaScript顯示函數(shù)調(diào)用堆棧的具體作用與使用方法,需要的朋友可以參考下2016-04-04微信小程序報(bào)錯(cuò):does?not?have?a?method?"xxxx"?to?ha
這篇文章主要給大家介紹了關(guān)于微信小程序報(bào)錯(cuò):does?not?have?a?method?"xxxx"?to?handle?event?"tap"的解決方案,文中將解決的辦法介紹的非常詳細(xì),需要的朋友可以參考下2023-01-01在TypeScript中迭代對(duì)象鍵Object.keys不起作用的原因和解決方案
在TypeScript中迭代對(duì)象鍵object?keys可能是一場(chǎng)噩夢(mèng),以下是我所知道的所有解決方案,文中有詳細(xì)的代碼示例供大家參考,具有一定的參考價(jià)值,需要的朋友可以參考下2023-10-10wangEditor編輯器失去焦點(diǎn)后仍然可以在原位置插入圖片分析
本文給大家?guī)淼氖且豢罘浅2诲e(cuò)的富文本編輯器WangEditor,他最大的特點(diǎn)是它在ie6,7,8上都可以做到失去焦點(diǎn)后仍然可以在原位置插入圖片,而且代碼量很少,下面我們就來分析下他是如何實(shí)現(xiàn)的呢2015-05-05