零基础微信落地页小程序实战项目
前言
微信小程序簡(jiǎn)單易上手,只要有一些編程基礎(chǔ),即可快速開(kāi)發(fā)基本的項(xiàng)目。
本項(xiàng)目是常見(jiàn)的,商品廣告落地頁(yè)小程序。提供商品瀏覽,商品列表按鈕,購(gòu)買(mǎi),微信授權(quán),手機(jī)號(hào)綁定,驗(yàn)證碼校驗(yàn),用戶協(xié)議,消息通知,監(jiān)聽(tīng)者模式等基本功能。
定位學(xué)習(xí)人群是剛接觸微信小程序的,零基礎(chǔ)同學(xué)。
本人剛接觸微信小程序時(shí),也是零基礎(chǔ),HTML和CSS都是第一次接觸,經(jīng)過(guò)兩個(gè)星期的學(xué)習(xí),就掌握了基本的開(kāi)發(fā)技巧,并獨(dú)立完成多個(gè)項(xiàng)目。所以即使沒(méi)有這方面經(jīng)驗(yàn)的同學(xué)也不要?dú)怵H,只要學(xué)習(xí)幾個(gè)實(shí)戰(zhàn)項(xiàng)目之后,應(yīng)付工作基本上都是綽綽有余的。
效果圖展示:
目錄
創(chuàng)建小程序
落地頁(yè)可適配長(zhǎng)度界面
落地頁(yè)底部欄:
- 客服按鈕,購(gòu)買(mǎi)按鈕
- 微信登錄授權(quán)
- 底部用戶協(xié)議,用戶協(xié)議同意定位
3 x 3 按鈕組件
- 組件使用
- flex-grow
- flex-shrink
- 組件傳遞數(shù)據(jù)
- CSS關(guān)鍵幀動(dòng)畫(huà)
拼團(tuán)成功組件
廣告輪播
- 水平廣告輪播
- 消息輪播
下浮層
Notification 監(jiān)聽(tīng)者模式
Toast 提示彈窗
總結(jié)
代碼下載
創(chuàng)建
創(chuàng)建一個(gè)小程序項(xiàng)目,如果只是學(xué)習(xí),那只需要下載安裝 微信開(kāi)發(fā)者工具。如果是商用的話,需要申請(qǐng)APPID,并根據(jù)自己需要開(kāi)通相應(yīng)的功能,例如支付接口,以及申請(qǐng)自己的資源CDN。
下面介紹如何創(chuàng)建一個(gè)小程序:
啟動(dòng)工具之后,點(diǎn)擊“+” 創(chuàng)建小程序。
如果沒(méi)有申請(qǐng) APPID,可以使用測(cè)試號(hào),就是隨機(jī)生成的測(cè)試號(hào),只是本地開(kāi)發(fā)使用,不可以商用。
選擇 不使用云服務(wù),點(diǎn)擊創(chuàng)建,選擇編程語(yǔ)言。然后點(diǎn)擊確定。
這樣就來(lái)到項(xiàng)目界面。
— NEXT —
落地頁(yè)可適配長(zhǎng)度界面
本小節(jié),我們來(lái)實(shí)現(xiàn)一下落地頁(yè)可適配長(zhǎng)度的滾動(dòng)界面。
需要?jiǎng)?chuàng)建 page,名稱(chēng)就叫做 landingpage。
在app.json中,添加啟動(dòng)頁(yè),輸入名稱(chēng),按下回車(chē),會(huì)自動(dòng)在 pages/ 路徑下生成文件夾,并生成 landingpage.js,landingpage.json,landingpage.wxml,landingpage.wxss 四個(gè)文件。
我習(xí)慣先寫(xiě) .wxml 文件,然后在 .wxss 文件中隨時(shí)調(diào)試界面樣式,涉及到引用的組件,在 .json 文件中添加即可。界面邏輯寫(xiě)在 .js 文件中。
分析界面結(jié)構(gòu):
- 整體結(jié)構(gòu)為縱向垂直布局,可以先設(shè)置幾張圖片依次平鋪。
先設(shè)置 landingpage 整體樣式:
<view class='main-wrap'></view>
.main-wrap {position: relative;display: flex;flex-direction: column;background: #EEE; }使用 wx:for 設(shè)置一組圖片,wx:key可以寫(xiě)成 *this
<block wx:for="{{bannerImgList}}" wx:for-index="index" wx:key="*this"><image class="banner" mode="widthFix" src="{{item}}" lazy-load="true" /> </block>圖片樣式為:
.banner {width: 100%;height: auto; }這里 bannerImgList 為本地一組圖片資源,在 data 中聲明:
bannerImgList: ['../../images/landingpage1.jpg','../../images/landingpage6.jpg','../../images/landingpage7.jpg','../../images/landingpage8.jpg', ]這樣,落地頁(yè)基本就有了一個(gè)簡(jiǎn)單的界面,圖片從上到下鋪滿屏幕。
注意這里的圖片在實(shí)際項(xiàng)目中,需要使用CDN的下載地址,不然本地資源太多,影響小程序加載速度,而且上傳小程序也有尺寸限制。
Tips:
- 書(shū)寫(xiě) wxml 標(biāo)簽快捷方式:
- 輸入 view . className 回車(chē),會(huì)自動(dòng)生成 <view class=“className”></view>
- 輸入 view # idName 回車(chē),會(huì)自動(dòng)生成 *<view id=“idName”></view>,其他標(biāo)簽同理。
- 微信小程序,自定義組件不支持 id 選擇器,所以注意在組件中要使用類(lèi)選擇器。
- 圖片加載方式設(shè)置為 lazy-load 表示需要顯示圖片時(shí)才顯示,這樣做能提高界面刷新效率。
— NEXT —
落地頁(yè)底部欄:
本小節(jié),我們布局底部欄,包含用戶協(xié)議,和兩個(gè)按鈕。
分析界面布局
- 上下兩層結(jié)構(gòu),內(nèi)部為水平布局。
先創(chuàng)建一個(gè)bottom容器:
<view class="bottom-box"></view>
再添加兩個(gè)按鈕和文字:
<view id="bottom-wrap" style="padding-bottom:{{safeAreaHeight}}rpx;"><view id="kefu" bindtap="tapKefu" hover-class="button-hover"><image id="kefu-icon" mode="widthFix" src="../../images/kefu.png"></image><text id="kefu-txt">咨詢</text></view><button class="button-normal" hover-class="button-hover" bindtap="getUserProfile">購(gòu) 買(mǎi)</button> </view>Tips:
- bindtag ??按鈕點(diǎn)擊事件的回調(diào)函數(shù)名稱(chēng)
- hover-class ??按鈕選中樣式
- getUserProfile ??是微信授權(quán)接口,固定寫(xiě)法
- safeAreaHeight ??是為了適配
樣式如下:
#bottom-wrap {position: fixed;width: 100%;bottom: 0;z-index: 1;background: #fff;display: flex;flex-direction: row;/* padding-bottom: constant(safe-area-inset-bottom);padding-bottom: env(safe-area-inset-bottom); */ }#kefu {position: relative;margin-top: 10rpx;margin-left: 30rpx;width: 200rpx;height: 100rpx;display: flex;flex-direction: row;border: 2rpx solid green;border-radius: 100rpx;background-color: #EEE;justify-content: space-evenly;align-items: center; }#kefu-icon {margin: 0;padding: 0;width: 70rpx;height: 70rpx; }#kefu-txt {margin: 0;padding: 0;font-size: 30rpx;line-height: 30rpx;color: green; }.button-normal {position: relative;padding: 0;margin: 10rpx;margin-right: 30rpx !important;width: 400rpx !important;height: 100rpx;display: flex;flex-direction: row;border-radius: 100rpx;background-color: #FF6400;align-items: center;justify-content: center;font-size: 40rpx;color: #fff; }.button-hover {opacity: 0.75; }Tips:
- constant(safe-area-inset-bottom) 和 env(safe-area-inset-bottom)
是適配 iPhoneX 底部 “Dock” 欄的方法。但是適配的高度偏高,這里還是使用自定義高度。 - position 是標(biāo)簽需要經(jīng)常使用的定位屬性,一般常用的是
- position: relative; 相對(duì)位置
- position: absolute; 絕對(duì)位置,常用于浮動(dòng)在父級(jí)節(jié)點(diǎn)上,不會(huì)撐起父級(jí)容器。
- position: fixed; 固定位置,常用于固定在界面的下方或者上方,不會(huì)隨著窗體滾動(dòng)而變化位置。
自定義適配高度,具體計(jì)算規(guī)則在如下代碼中:
const system = wx.getSystemInfoSync(); const windowHeight = Math.round(system.windowHeight); const safeArea = system.safeArea && system.safeArea.top > 20 ? system.safeArea : { top: 0 }; const safeAreaHeight = safeArea.top / 2;- 底部欄需要始終固定在屏幕最下方,所以使用 position: fixed
客服按鈕,購(gòu)買(mǎi)按鈕
微信登錄授權(quán)
- getUserProfile 是微信官方提供的接口,用于喚起用戶微信授權(quán)。
可以獲得用戶的用戶名,微信昵稱(chēng),頭像地址等個(gè)人信息。
如果用戶不同意,那么不會(huì)獲得相應(yīng)的數(shù)據(jù)。
并且該 API 無(wú)法主動(dòng)調(diào)起,必須通過(guò)綁定點(diǎn)擊事件。
這里包含成功,失敗,還有完成(無(wú)論成功失敗都會(huì)走的),三個(gè)處理函數(shù)。可以在這里實(shí)現(xiàn)業(yè)務(wù)邏輯。
底部用戶協(xié)議,用戶協(xié)議同意定位
一般界面都會(huì)設(shè)計(jì)諸如 “用戶協(xié)議”,”個(gè)人信息保護(hù)聲明“,“電信業(yè)務(wù)經(jīng)營(yíng)許可證”,之類(lèi)的信息。
如下:
<!-- 備案信息 --> <view class="question-wrap"> <view class="record-wrap"><image class="choose-record"src="{{chooseRecord ? chooseRecordImg : unChooseRecordImg}}"catchtap="tapChoose" /><text>我同意</text><text class="record" catchtap="tapRecord">《個(gè)人信息授權(quán)及保護(hù)聲明》</text><text>和</text><text class="record" catchtap="tapRecord">《用戶協(xié)議》</text> </view> <text class="question-desc">XXXXXXXX公司 京ICP備123456789號(hào)</text> </view>其實(shí)就是幾個(gè)文字和URL組成的。
這里點(diǎn)擊授權(quán)信息,跳轉(zhuǎn)到一個(gè)內(nèi)嵌的 webView 界面,顯示 H5 鏈接。我就暫時(shí)寫(xiě)成 bai du 地址了,可以替換成真實(shí)業(yè)務(wù)地址。
const h5 = 'www.baidu.com'; const url = `../../pages/commonWebView/commonWebView? url=${encodeURIComponent(h5)}&share=false`; wx.navigateTo({ url });commonWebView頁(yè)面也很簡(jiǎn)單,只需要實(shí)現(xiàn)對(duì)應(yīng)的回調(diào)函數(shù)即可,詳細(xì)代碼實(shí)現(xiàn),可下載代碼包,仔細(xì)查看,這里篇幅有限不再占用。
<web-view src="{{url}}" bindmessage="webViewObserverMessage" bindload="webViewLoadSuccess" binderror="webViewLoadError" />
— NEXT —
3 x 3 按鈕組件
在落地頁(yè)經(jīng)常需要實(shí)現(xiàn)一個(gè)可以點(diǎn)擊的按鈕列表,為用戶提供直觀的可選產(chǎn)品。
組件使用
這里新建一個(gè) <Fruits></Fruits> 水果按鈕列表組件。
分析界面結(jié)構(gòu):
- 縱向三層,整體居中。
- 第一層是標(biāo)題 “請(qǐng)選擇水果”,外加兩個(gè)小手動(dòng)畫(huà)。內(nèi)部是水平布局。
- 第二層是 3 x 3 按鈕列表,里面有文字,有點(diǎn)擊事件,有按鈕樣式,整體居中布局。
- 第三層是一個(gè)居中布局的文字。
結(jié)構(gòu)很簡(jiǎn)單,開(kāi)始動(dòng)手寫(xiě) wxml
<view class="title-wrap"> <image class="finger" src="{{fingerImg}}"/> <text>請(qǐng)選擇要購(gòu)買(mǎi)的水果</text> <image class="finger" src="{{fingerImg}}"/> </view><view class="fruits-list"> <view class="fruit" wx:for="{{fruitsList}}" wx:key="index" data-index="{{index}}" catchtap="tapFruit"><text>{{item}}</text><button class="fruit-btn" bindtap="getUserProfile" data-index="{{index}}"></button> </view> </view><view class="tips">{{'*購(gòu)買(mǎi)成功記得五星好評(píng)哦'}}</view>樣式:
.title-wrap {margin: 40rpx auto;padding: 0;display: flex;flex-direction: row;justify-content: space-between;flex-grow: 1;flex-shrink: 1;font-size: 34rpx;color: #000;font-family: PingFangSC-Semibold,PingFang SC; }.finger {width: 44rpx;height: 50rpx; }.fruits-list {position: relative;margin: 0 50rpx;display: flex;flex-flow: row wrap; }.fruit {position: relative;margin: 0 8rpx 24rpx;width: 200rpx;background: #fff;border: 2rpx solid rgba(255, 107, 44, 1);border-radius: 10rpx;font-size: 28rpx;line-height: 72rpx;font-weight: 600;color: rgba(255, 98, 3, 1);text-align: center; }.fruit:nth-child(3n+1) {margin-left: 0; }.fruit:nth-child(3n) {margin-right: 0; }.fruit-btn {background: transparent;width: 100% !important;height: 100%;z-index: 1;position: absolute;top: 0;bottom: 0;left: 0;right: 0; }.tips {margin: 12rpx 30rpx 38rpx;font-size: 24rpx;font-weight: 300;color: #999999;line-height: 24rpx;letter-spacing: 1rpx;text-align: center; }Tips:
- 小手指是上下移動(dòng)的,可以使用CSS關(guān)鍵幀動(dòng)畫(huà)實(shí)現(xiàn)
- 按鈕列表中,需要綁定按鈕序號(hào),使用 data-index 綁定循環(huán)中的序號(hào)。
- 節(jié)點(diǎn)自適應(yīng)左右居中常用的方法就是設(shè)置 margin: 0 auto 。
這里面用到了 flex-grow 和 flex-shrink。著重簡(jiǎn)單介紹一下,因?yàn)檫@兩個(gè)屬性經(jīng)常會(huì)用到。
flex-grow
flex-grow 處理父元素在還有剩余空間時(shí)的分配規(guī)則,分為兩種情況。
即:所有元素的 flex-grow 值之和大于1,和小于1。
大于1時(shí),例如:
父元素寬600,子元素A和B,寬分別為200,300。還剩余100。
此時(shí)A,B的 flex-grow 分別為2,3。則剩余100,分給A 2/5,分給B 3/5。
A,B寬度為:
小于1時(shí),作為分母的總和會(huì)引入1來(lái)處理。例如:
上例中,A,B flex-grow 分別為 0.2,0.3。則分給A 0.2/1,分給B 0.3/1。
A,B寬度為:
還剩50沒(méi)有分配給任何子元素?cái)U(kuò)張。
另外,flex-grow 還會(huì)受到父元素的 max-width 影響。如果grow后的結(jié)果超出 max-width,max-width 會(huì)優(yōu)先生效。
flex-shrink
和 flex-grow 處理父元素剩余空間相對(duì)應(yīng)的,是 flex-shrink 處理父元素空間不足時(shí),子元素的收縮規(guī)則。
同樣分為兩種情況,所有元素的 flex-shrink 值之和大于1,和小于1。
大于1時(shí),例如:
父元素寬度為600,子元素寬度為400,300。超出100。
A,B flex-shrink 分別為 1,2。總權(quán)重為 400 + 300 * 2 = 1000
A,B實(shí)際寬度為:
小于1時(shí),例如,
A,B flex-shrink 分別為 0.1,0.2。總權(quán)重為 400 * 0.1 + 300 * 0.2 = 100
子元素收縮總和為 100 * 0.3 / 1 = 30
A,B實(shí)際寬度為:
多出70沒(méi)有分配給任何子元素收縮。
同樣,也會(huì)受到min-width的限制。
組件傳遞數(shù)據(jù)
父組件向子組件傳遞數(shù)據(jù)
在組件的屬性列表中新增參數(shù)字段:
properties: {option: {type: Boolean,value: true} }這個(gè)屬性需要在使用組件的位置賦值,并作為參數(shù)傳遞下去:
<Fruits option="{{true}}"></Fruits>
子組件向父組件傳遞數(shù)據(jù)
在子組件內(nèi) trigger 一個(gè)事件,然后在子組件被引用的位置 bind 事件。并且在事件響應(yīng)函數(shù)中,使用傳遞過(guò)來(lái)的數(shù)據(jù)。
-
Trigger: this.triggerEvent('eventName', { index }); 可以在后面夾帶參數(shù)。
-
Bind: <Fruits option="{{true}}" bindeventName="callBack"></Fruits>
-
CallBack:
callBack: function (e) {// 事件傳遞過(guò)來(lái)的參數(shù)const index = e.detail.index; }
CSS關(guān)鍵幀動(dòng)畫(huà)
為了實(shí)現(xiàn)手指向下的小動(dòng)畫(huà),使用關(guān)鍵幀處理。
如果在 @keyframes 規(guī)則中指定了 CSS 樣式,動(dòng)畫(huà)將在設(shè)定時(shí)間逐漸從當(dāng)前樣式更改為新樣式。
- 左右手各使用一個(gè)動(dòng)畫(huà),因?yàn)槿绻褂猛粋€(gè)動(dòng)畫(huà),再Y軸翻轉(zhuǎn)一下也可以。但是會(huì)出現(xiàn)左右動(dòng)畫(huà)不同時(shí)運(yùn)動(dòng)的問(wèn)題。
- 0.9s 是持續(xù)時(shí)間,infinite 是無(wú)限循環(huán)。
keyframes :
@keyframes moveDownLeft {0% {transform: translateY(0rpx);}50% {transform: translateY(9rpx);}100% {transform: translateY(0rpx);} }@keyframes moveDownRight {0% {transform: translateY(0rpx) scale(-1, 1);}50% {transform: translateY(9rpx) scale(-1, 1);}100% {transform: translateY(0rpx) scale(-1, 1);} }左手動(dòng)作設(shè)置了從開(kāi)始到一半,再到結(jié)束時(shí)的Y軸位移。右手Y軸動(dòng)作一致,只不過(guò)水平翻轉(zhuǎn)一下。
— NEXT —
拼團(tuán)成功組件
在落地頁(yè)中加入拼團(tuán)成功動(dòng)畫(huà)。同樣也是使用組件實(shí)現(xiàn)。
動(dòng)畫(huà)效果設(shè)計(jì)為,開(kāi)始顯示兩個(gè)人已在團(tuán)內(nèi),另有一個(gè)人的頭像在拼團(tuán)成功時(shí)飛入第三個(gè)頭像框,表示拼團(tuán)成功。同時(shí)文字由“即將成團(tuán)”變成“拼團(tuán)成功”。并且倒計(jì)時(shí)持續(xù)刷新。拼團(tuán)成功會(huì)有一個(gè)標(biāo)志章顯示出來(lái),然后頭像和拼團(tuán)文字整體向上滾動(dòng),最后刷新出下一組拼團(tuán)頭像。
最右側(cè)是一個(gè)去拼團(tuán)的點(diǎn)擊按鈕。
寫(xiě)動(dòng)畫(huà)的難點(diǎn)不是動(dòng)作怎樣寫(xiě),而是整體的節(jié)奏感是否協(xié)調(diào)。
分析界面布局:
縱向布局分三層
- 第一層標(biāo)題,里面水平結(jié)構(gòu),包含三個(gè)文字。
- 第二層頭像,文字,按鈕,另外還有一個(gè)飛動(dòng)的圖片。這里頭像又可以做成組件。
- 第三層是一個(gè)拼團(tuán)成功的圖片。
PinTuan組件
<view class="wrap"><view class="text-wrap"><text>還差</text><text class="persion-num">{{personNum}}人</text><text>成團(tuán),可直接參與</text></view><view class="pintuan-content"><PinTuanHead class="pin-tuan" headUrls="{{headUrls}}" animation="{{pinTuanAni}}" bindtransitionend="pinTuanAniEnd" isNeedLogin="{{isNeedLogin}}"></PinTuanHead><view class="join" animation="{{pinTuanAni}}" bindtransitionend="pinTuanAniEnd"><text class="join-text">{{joinText}}</text><text class="clock">還剩{{clockText}}</text></view><image animation="{{headAniData}}" bindtransitionend="headAniEnd" class="move-head" src="{{moveHead}}"></image><button class="goGroup" bindtap="getUserProfile">去參團(tuán)</button></view><image wx:if="{{pinTuanSuccess}}" class="successed" src="{{successedImg}}" mode="widthFix"animation="{{successAni}}" bindtransitionend="successAniEnd" style="transform: scale(0.3) opacity(0)"></image><view class="bottom-border"></view> </view>animation動(dòng)畫(huà)
使用animation動(dòng)畫(huà),可以實(shí)現(xiàn)復(fù)雜的動(dòng)作流程。動(dòng)畫(huà)的開(kāi)始和結(jié)束都需要處理邏輯。
創(chuàng)建動(dòng)畫(huà)后,需要導(dǎo)出一下,代碼實(shí)現(xiàn)如下:
先設(shè)置動(dòng)畫(huà)屬性,再設(shè)計(jì)動(dòng)畫(huà)運(yùn)動(dòng)軌跡,最后導(dǎo)出:
- timingFunction: 'ease' 設(shè)置緩動(dòng)效果。
- ani.opacity(0).translateY(-30).step(); 先透明度為0,然后Y軸坐標(biāo)。
- step() 表示一組動(dòng)畫(huà)完成。可以在一組動(dòng)畫(huà)中調(diào)用任意多個(gè)動(dòng)畫(huà)方法,一組動(dòng)畫(huà)中的所有動(dòng)畫(huà)會(huì)同時(shí)開(kāi)始,一組動(dòng)畫(huà)完成后才會(huì)進(jìn)行下一組動(dòng)畫(huà)。
- bindtransitionend 是設(shè)置動(dòng)畫(huà)結(jié)束時(shí)的回調(diào)函數(shù)。
代碼和樣式請(qǐng)下載資源包,對(duì)應(yīng) PinTuan 文件夾下,因篇幅有限,這里不列出詳細(xì)代碼
PinTuanHead組件
分析界面布局:
三個(gè)頭像,分為頭像背景圖,和真實(shí)頭像圖。并且需要?jiǎng)討B(tài)控制頭像顯示。
代碼和樣式在資源包 PinTuanHead 文件夾
Tips:
- 樣式中使用 :nth-child 表示同類(lèi)標(biāo)簽的第幾個(gè)標(biāo)簽。這類(lèi)偽標(biāo)簽可以節(jié)省 wxml 空間,減少 document 渲染的節(jié)點(diǎn)數(shù)量。
— NEXT —
廣告輪播
微信提供輪播圖組件,可以設(shè)置輪播間隔,提示點(diǎn),循環(huán)等屬性。
水平廣告輪播
設(shè)置一組圖片水平方向循環(huán)輪播
消息輪播
左上角設(shè)置縱向消息輪播。
分析界面布局:
- 水平布局,左邊是用戶頭像,右邊是文字。
- 文字顯示分兩種情況,如果是帶拼團(tuán)的,就隨機(jī)顯示“剛剛拼團(tuán)成功”和“剛剛參團(tuán)成功”文字。如果不帶拼團(tuán),就顯示“剛剛搶單成功”。
<view class="recent-payment-list-wrap"><swiper class="recent-payment-list" vertical="{{true}}" autoplay="{{true}}" interval="{{3000}}" circular="{{true}}"duration="{{500}}" capture-catch:touchmove='preventTouchMove'><block wx:for="{{recentPaymentUsers}}" wx:for-index="index" wx:key="index"><swiper-item><view class="recent-payment-cell"><view class="recent-payment-cell-content"><image class="recent-payment-avatar" src="{{item.avatar}}" mode="aspectFill" /><view class="recent-payment-name">{{item.name}}</view><view wx:if="{{showPinTuan}}"><view wx:if="{{item.pinTuanRandom}}" style="flex-shrink: 0;">剛剛拼團(tuán)成功</view><view wx:else style="flex-shrink: 0;">剛剛參團(tuán)成功</view></view><view wx:else style="flex-shrink: 0;">剛剛搶單成功</view></view><view style="flex-grow: 1;"></view></view></swiper-item></block></swiper></view>
代碼和樣式在資源包,landingpage 文件夾下
— NEXT—
下浮層
點(diǎn)擊水果按鈕,彈出注冊(cè)手機(jī)號(hào)下浮層。如果已經(jīng)注冊(cè)手機(jī)號(hào),彈出訂單詳情彈窗。
切換下浮層顯示通過(guò) promptStatus 值為0或者1決定。
下浮層封裝為組件 FruitPrompt,自定義組件的顯隱,不能通過(guò)設(shè)置 hidden 實(shí)現(xiàn)。可以設(shè)置 wx:if 條件判斷顯示。
為了方便處理下浮層的顯示,設(shè)置一個(gè)浮層基類(lèi)組件 Prompt,FruitPrompt 繼承自 Prompt
Prompt:
<view class='prompt {{slowDown?"hideOpacity":""}}' data-type="mask" catchtap='closeCallback' catchtouchmove='touchMove'><view class='container {{slowDown?"slowDown":""}}' catchtap='catchEvent'><view class='title'>{{title}}</view><image src='{{iconClose}}' class='icon' catchtap='closeCallback' data-type="button" /><slot></slot><view wx:if="{{showButton}}" class='btnContainer'><button class="menuBtn" bindtap="btnCallback">{{btnText}}</button></view></view> </view>注冊(cè)手機(jī)號(hào),獲取驗(yàn)證碼,驗(yàn)證碼倒計(jì)時(shí)
分析界面布局
縱向布局:
- 手機(jī)號(hào)和驗(yàn)證碼用到 input 標(biāo)簽。
- 輸入手機(jī)號(hào)和驗(yàn)證碼之后,“獲取驗(yàn)證碼” 按鈕高亮,并可以點(diǎn)擊。
注冊(cè)手機(jī)號(hào),需要實(shí)現(xiàn)驗(yàn)證碼功能,點(diǎn)擊獲取驗(yàn)證碼,校驗(yàn)手機(jī)號(hào)輸入合法性。合法則申請(qǐng)驗(yàn)證碼,并且進(jìn)入 60s 倒計(jì)時(shí)。
驗(yàn)證碼倒計(jì)時(shí)部分,利用 setInterval 封裝一個(gè)公共的倒計(jì)時(shí)函數(shù),提供異步回調(diào)函數(shù)。
function initCountdown({isCheck: isCheck = false,name: name,timeTotal: timeTotal,timeInterval: timeInterval,checkCallback: checkCallback,timeChangedCallback: timeChangedCallback,endCallback: endCallback }) {if (typeof name !== 'string' || !name) {return;}const countdownInterval = countdownMap[name];if (countdownInterval) {clearInterval(countdownMap[name].interval);} else if (isCheck) {if (typeof checkCallback === 'function') {checkCallback();}return;} else {countdownMap[name] = {timeTotal: timeTotal,timeInterval: timeInterval};}if (typeof timeChangedCallback === 'function') {timeChangedCallback(countdownMap[name].timeTotal);}countdownMap[name].interval = setInterval(() => {if (countdownMap[name].timeTotal <= 0) {clearInterval(countdownMap[name].interval);delete countdownMap[name];if (typeof endCallback === 'function') {endCallback();}return;}countdownMap[name].timeTotal -= countdownMap[name].timeInterval;if (typeof timeChangedCallback === 'function') {timeChangedCallback(countdownMap[name].timeTotal);}}, countdownMap[name].timeInterval); }在點(diǎn)擊驗(yàn)證碼按鈕時(shí),觸發(fā)倒計(jì)時(shí)。
initCountdownManager(isCheck) {countdownManager.initCountdown({isCheck: isCheck,name: 'bindPhone.verifyCode',timeTotal: 60000,timeInterval: 1000,checkCallback: () => {this.data.countingdown = false;},timeChangedCallback: countdown => {this.setData({inputCodeButtonTitle: `重新發(fā)送(${parseInt(countdown / 1000)}s)`,inputCodeButtonStyle: 'color: #CCCCCC;'});},endCallback: () => {this.setData({inputCodeButtonTitle: '重新發(fā)送',inputCodeButtonStyle: 'color: #FF8134;'});this.data.countingdown = false;}}); }Tips:
- setData 函數(shù)用于將數(shù)據(jù)從邏輯層發(fā)送到視圖層(異步),同時(shí)改變對(duì)應(yīng)的 this.data 的值(同步)。
- 如果更新數(shù)據(jù)之后,沒(méi)有使用 setData 函數(shù)
例如: this.data.countingdown = false 則只是將數(shù)據(jù)寫(xiě)入 this.data,不能刷新界面顯示。
訂單詳情
設(shè)計(jì)顯示售罄標(biāo)記,先到先得標(biāo)記。
分析界面布局:
縱向結(jié)構(gòu);
- 水果按鈕列表,3 x 3 列表。
- 按鈕右上角設(shè)置標(biāo)簽。
- 訂單介紹,保質(zhì)期時(shí)長(zhǎng)。介紹按鈕右上角有標(biāo)簽。
代碼和樣式請(qǐng)下載資源包,對(duì)應(yīng) FruitPrompt 文件夾下,因篇幅有限,這里不列出詳細(xì)代碼
Notification 監(jiān)聽(tīng)者模式
處理邏輯,經(jīng)常需要用到監(jiān)聽(tīng)者模式。實(shí)際原理很簡(jiǎn)單,只需一個(gè)數(shù)組,將需要監(jiān)聽(tīng)的對(duì)象和鉤子函數(shù)壓棧,然后在捕獲到鉤子時(shí),在出棧。
[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來(lái)直接上傳(img-9cV8cQRN-1633762407320)(soldout.png)]
// 發(fā)送通知 function postNotification(notificationName, data = {}) {for (let i = 0; i < observerList.length; i++) {const observer = observerList[i];if (notificationName === observer.name) {observer.selector(data);}} }
— NEXT —
Toast 提示彈窗
封裝各種提示彈窗。使用 wx.showToast 我們?cè)俜庋b一層,可以提示各種自定義信息,也可以加自定義 icon。
// 文字提示框 function showTextToast(title, cb, seconds, mask = true) {showToast({title: title,icon: 'none',mask: mask,callback: cb,seconds: seconds}) }// 加載提示框 function showLoadingToast(title, cb, seconds) {showToast({title: title,icon: 'loading',mask: true,callback: cb,seconds: seconds}) }// 成功提示框 function showSuccessToast(title, cb, seconds) {showToast({title: title,icon: 'success',mask: true,callback: cb,seconds: seconds}) }// 錯(cuò)誤提示框 function showErrorToast(title, cb, seconds) {showToast({title: title,image: 'XXXX',icon: 'none',mask: true,callback: cb,seconds: seconds}) }// 文字提示框 function showToast({title: title,icon: icon,image: image,mask: mask,callback: callback,seconds: seconds }) {if (!title) {if (callback) {callback()}return;}if (!seconds) {seconds = 1.7;}wx.showToast({title: title,icon: icon,image: image,mask: mask,duration: seconds * 1000});setTimeout(function () {if (callback) {callback()}}, seconds * 1000); }
總結(jié)
微信小程序開(kāi)發(fā),常用標(biāo)簽和 style 樣式并不多,很容易掌握。
常用 wxml 標(biāo)簽:
- view 當(dāng)作節(jié)點(diǎn)使用
- image 圖片
- text 文字
- block 不占位標(biāo)簽
- swiper 輪播
- scroll-view 滾動(dòng)層
- web-view H5內(nèi)嵌
- input 輸入框
- button 按鈕
常用 style 樣式
- position: relative, absolute, fixed 設(shè)定節(jié)點(diǎn)坐標(biāo)
- margin, padding 設(shè)定節(jié)點(diǎn)邊距,margin是外邊距,padding是內(nèi)邊距
- display 設(shè)定元素的顯示類(lèi)型
- width, height 寬高
- top, bottom, left, right 設(shè)定 absolute 坐標(biāo)后設(shè)定上,下,左,右,間距
- background 背景,可以設(shè)定顏色,背景圖片,背景尺寸
- z-index Z 軸優(yōu)先級(jí)
- font 字體,可以設(shè)定字體庫(kù),字體顏色,陰影,描邊,字體大小,字間距,行間距
- border 邊框,圓角,自定義邊角
- animation 動(dòng)畫(huà),可以設(shè)定逐幀動(dòng)畫(huà),也可以綁定動(dòng)畫(huà)事件
常用技巧
居中:
- 左右居中:父節(jié)點(diǎn)需要設(shè)置 display:flex; 然后子節(jié)點(diǎn)設(shè)置 margin: 0 auto; 子節(jié)點(diǎn)可以水平左右居中。
- 節(jié)點(diǎn)內(nèi)容居中:同樣,也需要父節(jié)點(diǎn)設(shè)置 display:flex; 然后父節(jié)點(diǎn)再設(shè)置 align-items: center; 可以實(shí)現(xiàn)內(nèi)部元素水平和垂直都居中。
- 文字水平居中:設(shè)置父節(jié)點(diǎn) text-align: center; 可以實(shí)現(xiàn)內(nèi)部文字水平居中。
- 文字垂直居中:text 標(biāo)簽 font-size 和 line-height 設(shè)置一致時(shí),文字垂直居中。
- 依靠元素顯示類(lèi)型居中:display: flex; justify-content: center; // 水平居中 vertical-align: middle; // 垂直居中
— NEXT —
代碼下載
鏈接: 百度云盤(pán)下載
密碼: 9ia8
云盤(pán)二維碼:
總結(jié)
以上是生活随笔為你收集整理的零基础微信落地页小程序实战项目的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 领券中心项目,我是如何用 Redis 做
- 下一篇: 太平洋保险集团A+H上市方案生变 年内先