我是一名安卓程式設計師,以前沒有接觸過前端開發,直到有幸接手了公司的小程式專案。小程式學起來還是很快的,對於有程式設計經驗的人,看著示例程式碼,對照著官方文件,幾天就能上手了。
自從接觸了小程式,一直想做一個自己的東西,要是每天有點人用就更好了。
有一天和我家寶寶玩成語接龍,突然想到,我可以做一個成語接龍的小程式啊!
產品
琢磨了兩天,大概想做成這樣:
接龍可以有「所有人可參與」、「指定群成員參與」等型別
不校驗是否是成語,否則就無法使用「印賊做父」了
成語的讀音,還是要校驗一下的
難免會有人亂填,所以每條成語可以贊,也可以踩
在有一定資料量後可以增加排行榜
設計
想法有了,還有兩件比較棘手的事:
起個牛逼的名字
求我家寶寶給我畫設計圖
我想過很多名字,「成語接龍吧」、「接下去」、「接吧」、「接一個」...
寶寶:low 爆了,叫「碰詞」,碰也有接的意思,成語也是個詞嘛
這麼 6 的名字居然有人先想到了,於是最終決定用「碰詞er」
隨便放兩張設計圖,美如畫啥的就不說了:
下面說一下在開發方面,幾個我認為值得一提的地方。
獲取使用者資訊
現在大部分的小程式都是一開啟,就彈出使用者資訊授權框,有的甚至強制需要授權才可使用。我之前做的一個也是需要拿到 unionId 去登入才能使用的,為此我還寫過一篇文章說明如何實現。
但顯然,微信認為這是一個很不好的體驗。在使用者沒有接觸你的小程式之前,憑什麼要信任你,把自己的使用者資訊暴露給你。
為了規範使用者資訊的獲取,官方出了這篇文章:獲取使用者資訊方案介紹(FAQ 裡面有兩個問題還是我提的)
剛好拿這個小程式來實踐一下。
首先,明確什麼情況下需要用到使用者資訊。這裡需要使用者資訊顯示在成語旁,所以在建立接龍或者傳送成語之前,需要先獲取到使用者資訊。如果你只是進來看看,是不需要你任何授權的,只有點選了建立接龍的按鈕,或者傳送成語的按鈕,才會彈出授權提示框。
我是這樣做的。沒有使用者資訊時,設定 button 的 open-type 為 getUserInfo,點選會觸發使用者資訊的獲取。要是已經有使用者資訊了,則是一個普通的跳轉按鈕:
<view class="create-button">
<button wx:if="{{hasUserInfo}}" class="button" bindtap="navigateToCreate">
<image class="img" src="/images/icon_add.png" mode="aspectFit"/>
</button>
<button wx:else class="button" open-type="getUserInfo" bindgetuserinfo="getUserInfo">
<image class="img" src="/images/icon_add.png" mode="aspectFit"/>
</button>
</view>複製程式碼
當使用者確定授權了,可以在 bindgetuserinfo 繫結的方法裡,用 e.detail.userInfo 拿到使用者資訊。
但還有個問題,open-type="getUserInfo" 要到基礎庫 1.3.0 才能用,最好還是做一下低版本相容處理。
群能力
目前,小程式已經支援獲取到微信群的群 id 和顯示群名。
當使用者建立的接龍型別是指定群成員參與時,指定的群就是第一個轉發到的群。而成員也只有通過這個群的分享進入小程式,才可參與接龍。下面說說這兩種情況是如何獲取到群 id 的。
在可分享的頁面,呼叫 wx.showShareMenu() 顯示轉發按鈕。新增 onShareAppMessage 方法,並在裡面設定分享資訊:
onShareAppMessage: function () {
var that = this
return {
title: "一起來玩成語接龍!",
path: 'pages/xxx/xxx?id=' + this.data.id,
success(res) {
that.getShareInfo(res.shareTickets[0])
}
}
}複製程式碼
在 getShareInfo 方法裡,需要獲取到分享資訊,現在能獲取到的只有群 id:
wx.getShareInfo({
shareTicket: shareTicket,
success(res) {
// 解密獲取到 openGId
}
})複製程式碼
這裡和 getUserInfo 一樣,拿到的資料是加密的,需要將 res.encryptedData 和 res.iv 傳給後臺解密。加密方式和 userInfo 是一樣的,所以可以用同一個介面解密。解密後的 openGId 就是我們要的群 id。
至於從微信群進入的情況,我們需要對 app.js 的 onLaunch 方法動手。在 onLaunch 方法裡可以獲取到一個場景值,它區分了各種進入小程式的場景,各種場景值說明可以在這裡查到。其中可以看到:
當場景值為 1044 時,我們就可能獲取到攜帶的 shareTicket:
onLaunch: function (ops) {
if (ops != null && ops.scene == 1044) {
this.globalData.shareTicket = ops.shareTicket
}
}複製程式碼
之後再對這個 shareTicket 進行解密,獲取 openGId,判斷使用者是否可參與。
聊天列表
從設計圖可以看到,成語列表是置底的,類似微信聊天的效果。但列表都是預設置頂的,如何讓它置底呢?
其實很簡單,這裡利用了 scroll-view 元件的 scroll-into-view 屬性:
注意這裡有個細節,id 不能以數字開頭,但我的 id 就是數字開頭的怎麼辦?前面隨便加個字母就好了:
<scroll-view class="scroll" scroll-y="true" scroll-into-view="x{{toView}}">
<!-- ...... -->
</scroll-view>複製程式碼
item 的 id 前面也記得加個 x。
然後在獲得頁面資料 setData 之後,將列表定位到底部:
setTimeout(function () {
that.setData({
toView: list[list.length - 1].id
})
}, 300)複製程式碼
這裡的延時是不可少的,因為頁面渲染需要點時間,不同效能的手機需要的時間還不一樣。看過幾臺手機,300 毫秒應該是比較合適的。
如果要實現滑動到頂部載入更多的話,可以用上 bindscrolltoupper 這個屬性:
獲取更多後,將 toView 設定為新獲取到的列表最後一項的 id。
浮動按鈕
首頁右下角的按鈕美如畫,但是它會造成一定的遮擋。
安卓裡有一個叫 FloatActionButton 的控制元件,當列表滾動時,可以向下移動隱藏,我嘗試在小程式裡實現類似的效果。
我覺得遮擋其實只對列表最底部有影響,所以當列表滾到底部時隱藏就好了,發生滾動再顯示。
在不使用 scroll-view 的情況下,頁面觸底會觸發 onReachBottom 方法,滾動會觸發 onPageScroll 方法,所以這個功能可以這樣實現:
js
onReachBottom: function (event) {
// 隱藏按鈕,避免遮擋
this.setData({
showBtn: false
})
},
onPageScroll: function (event) {
// 顯示建立按鈕
this.setData({
showCreateBtn: true
})
}複製程式碼
wxml
<view class="button {{showBtn?'show-button':'hide-button'}}"/>複製程式碼
wxss
.show-button {
transform: translateY(0);
transition: 0.3s;
}
.hide-button {
transform: translateY(180rpx);
transition: 0.3s;
}複製程式碼
是不是很簡單,效果還不錯:
但是這裡面有兩個坑:
在開發工具上沒什麼問題,但在真機上,列表到達底部觸發 onReachBottom 之後,居然還會觸發 onPageScroll。我的做法是在 onReachBottom 之後的三百毫秒內不顯示按鈕。
在列表高度不滿螢幕高度時,向上滑動列表,也會觸發 onReachBottom,但是不會觸發 onPageScroll,導致隱藏後就不會再顯示了。解決方法是,可以先判斷列表是否可滾動,不可滾動的情況下不隱藏按鈕。
總結
剛開始,在沒有推廣的情況下,在我身邊的人都不願意玩的情況下,每天會有一兩百個新使用者。在上次知曉程式推薦過後,現在居然每天有一兩千個新使用者!流量費都快給不起了,非常感謝大家的捧場。
最後,感謝我家寶寶做了這麼好看的設計圖。