目的
為了深入學習微信小程序編程,設計一款簡潔的背單詞的小程序。
開發前准備
1.頁面結構
懶人單詞小程序的頁面有上下2個區域組成,content和tab。
content區域可以通過左右滑動實現標簽頁的切換。關於2個標簽具體說明:
-
單詞學習:顯示英語單詞書。
-
生詞本:顯示在單詞書里添加的不認識的單詞。
tab區域用於顯示“單詞學習”和“生詞本”2個標簽的標題。如果當前位於某個標簽下,該標簽頁會顯示紅色,並且字體也為紅色,其他標簽頁文字和線條顯示白色。
2.目錄結構
主要文件夾 | 說明 |
---|---|
index | 里面包含index.wxml,js,wxss和disbook.wxml |
study | 單詞學習頁面的結構、樣式和邏輯 |
BookDetail | 生詞詳情頁面的結構、樣式和邏輯 |
標簽頁切換
1.實現標簽頁的切換
swiper組件是滑塊容器視圖,用於輪播圖,本項目用於標簽頁的切換。
切換標簽頁有兩種方式,一種是直接滑動content區域,另一種是點擊tab區域中的某一個標簽對應切換。先為3個tab-item綁定事件,並設置data-item屬性。
<view class="tab-item {{tab==0?'active':''}}" bindtap="changeItem" data-item="0">單詞學習</view>
<view class="tab-item {{tab==1?'active':''}}" bindtap="changeItem" data-item="1">生詞本</view>
上述代碼中,data-item的值表示swiper 組件中對應的 swiper-item的索引。
接下來修改content區域,為swiper組件的current屬性綁定變量item,如下:
<view class="content">
<swiper current="{{item}}" >
完成后在js文件中,將changeItem中 item的值設為data-item的值,如下:
changeItem: function(e) {
this.setData({
item: e.target.dataset.item,
})
}
使用e.target.dataset.item 會獲取當前點擊的元素的 data-item 的item 值。
切換標簽頁后改變當前標簽樣式,通過判斷變量tab 的值來為當前活躍的data-item 增加一個 active 樣式,具體代碼:
<view class="tab-item {{tab==0?'active':''}}" bindtap="changeItem" data-item="0">單詞學習</view>
<view class="tab-item {{tab==1?'active':''}}" bindtap="changeItem" data-item="1">生詞本</view>
active樣式:
.tab-item.active {
color: #c25b5b;
border-bottom-color: #c25b5b;
}
為了更改tab值,給swiper組件綁定改變事件,如下:
<view class="content">
<swiper current="{{item}}" bindchange="changeTab">
changeTab會在swiper組件發生標簽頁切換時調用。如下:
data:{
item: 0,
tab: 0,
},
changeTab: function(e) {
this.setData({
tab: e.detail.current
})
}
單詞學習
1.單詞書頁面
view 布局 添加類名,綁定catchtab點擊事件,如下:
<view class="list-item" catchtap="clickFirst">
<image src="../images/four.jpg" />
<view>四級單詞</view>
</view>
bindtap :子元素使用bindtap綁定事件后,執行的時候,會冒泡到父元素(觸發父元素上綁定的bingtap事件)
catchtap :不會冒泡到父元素上,阻止事件冒泡
catchtab點擊事件的跳轉用wx.navigateto,js代碼如下:
clickFirst: function () {
wx.navigateTo({
url: '../study/detail?title=四級單詞',
})
},
wx.navigateto:保留當前頁面,跳轉到應用內的某個頁面。但是不能跳到 tabbar 頁面。使用 wx.navigateBack 可以返回到原頁面。
wx.redirectTo:關閉當前頁面,跳轉到應用內的某個頁面。但是不允許跳轉到 tabbar 頁面。
2.單詞詳情頁面
分為內容區和按鈕區,內容區需要從數據庫中去獲取單詞信息,在應用到頁面上。js代碼如下:
var list = require("../../data/word-list");
Page({
data:{
words:"",
soundmark:"",
definition:"",
show:false,
},
onLoad: function (options) {
var title = options.title
if (title) {
wx.setNavigationBarTitle({
title: title,
})
}
var id = Math.floor(Math.random() * 499) + 1;
var word = list.wordList[id];
this.setData({
words: word.content,//數據存儲到data里的
soundmark: word.pron,
definition: word.definition,
show: false,
title: title,
});
},
list 是一個js 文件的單詞數據,通過options獲取上個頁面的title來選擇對應詞書的單詞,從list里面隨機取單詞,把獲取到的數據存進data中,在頁面顯示,如下:
<view class="cet">
<view class="wordPart">
<text class="word">{{words}}</text>
<view class="soundmark">
<image class = 'soundmark-icon' src = "../../pages/images/pron-icon.png"></image>
<text class = "word-pron" bindtap='read'>|{{soundmark}}|</text>
</view>
</view>
<text wx:if = "{{show}}" class = "word-definition">{{definition}}</text>
</view>
內容區顯示完成后,來編寫按鈕區,添加button,在按鈕上綁定監聽事件,如下:
<view class="btns">
<button class = "button miss" catchtap='show' wx:if='{{!show}}'>不認識</button>
<button class = "button miss" wx:if='{{show}}'>已加入錯詞本</button>
<button class = "button next" catchtap='next'>下一個</button>
<button class = "button back" catchtap='back'>返回首頁</button>
</view>
wx:if =‘{{!show}}’ 來判斷是否渲染該代碼塊,給show默認賦值 false,點擊后 為true ,在將該單詞加入雲數據庫wordlist里,代碼如下:
show: function () {
this.setData({
show: true
})
db.collection('wordlist').add({
data:{
content:this.data.words,//調用上面data里的數據
definition:this.data.definition,
pron:this.data.soundmark,
}
}).then(res=>{})
},
點擊下一個按鈕,在從list 中隨機取出一個單詞,代碼如下:
next: function () {
var data = {
title: this.data.title
}
this.onLoad(data);
},
3.生詞本
在標簽頁切換到生詞本時,生詞本將從雲數據庫中調出所有單詞,顯示在頁面上,代碼如下:
<scroll-view class="content-disbook" scroll-y><!-- scroll-view 滾動視圖,scroll-y 縱向滾動 ,並在WXSS里添加一個滾動高度 -->
<view wx:for="{{DataList}}" wx:key="_id"><!-- wx:for 遍歷顯示數據 -->
<view class="errorword">
<view data-val="{{item._id}}" bindtap="transfer">{{item.content}}</view>
</view>
</view>
</scroll-view>
scroll-view 組件用於實現可滾動視圖區域,scroll-y 允許縱向滾動,scroll-x 允許橫向滾動。
生詞本列表顯示寫在onShow()事件中,onShow方法是在每次從小程序的前后台切換時都執行的,onLaunch方法是在小程序加載時執行的,因為該頁面會多次切換所有選擇onShow(),代碼如下:
var opid = wx.getStorageSync('openid')
onShow:function(){/* 刷新的數據寫在onshow()里 */
let THIS = this
db.collection('wordlist').where({
_openid:opid
}).get().then(res => {
THIS.setData({
DataList:res.data
})
})
},
生詞本顯示的單詞應該是登陸該小程序用戶自己添加的,所以應該獲取用戶的openid,來和數據庫中單詞的_openid 字段進行配對,通過調用雲函數來獲取打開小程序用戶的openid,代碼如下:
// 雲函數入口文件
const cloud = require('wx-server-sdk')
cloud.init()
// 雲函數入口函數
exports.main = async (event, context) => {
const wxContext = cloud.getWXContext()
return {
event,
openid: wxContext.OPENID,
appid: wxContext.APPID,
unionid: wxContext.UNIONID,
}
}
在transfer 點擊事件中使用方法e.target.dataset.val會獲取當前點擊的元素的val 里的當前單詞_id值,通過對應id值跳轉到對應單詞的詳情頁面,代碼如下:
transfer(e){
var id=e.target.dataset.val;
wx.navigateTo({
url: '../BookDetail/BookDetail?id='+id,
})
},
跳轉到生詞本單詞的詳情頁面,頁面結構:內容區和按鈕區,代碼如下:
<view wx:for="{{words}}" wx:key="*this">
<view class="cet" >
<view class="wordPart">
<text class="word">{{item.content}}</text>
<view class="soundmark">
<image class = 'soundmark-icon' src = "../../pages/images/pron-icon.png"></image>
<text class = "word-pron" >|{{item.pron}}|</text>
</view>
</view>
<text class = "word-definition">{{item.definition}}</text>
<view class="btns">
<button data-val="{{item._id}}" bindtap="remove">已認識</button>
<button class = "button back" catchtap='back'>返回生詞本</button>
</view>
</view>
</view>
words 也可以遍歷循環,直接{{words.屬性名}} 調用
在生詞頁面跳轉到單詞詳情頁面時,初始加載寫在onLoad()里,代碼如下:
Page({
data:{
words:"",
},
onLoad:function(options){
var ids=options.id;//將列表頁面的id賦值
let that=this
db.collection('wordlist').where({//通過id查詢數據
_id:ids,
}).get().then(res => {
// res.data 包含該記錄的數據
that.setData({
words:res.data
})
})
已認識按鈕點擊后執行刪除操作,從數據庫中刪除該單詞,代碼如下:
remove:function(e){
var id=e.target.dataset.val;
db.collection('wordlist').where({
_id:id //通過id 刪除
}).remove({
success: function(res) {
}
})
wx.navigateBack()
},
暫時小程序的基本功能都已實現了,未來還會繼續添加完善更多的功能,比如增加單詞的趣味性玩法,好友PK等等。
下面附上小程序截圖:
CSS樣式代碼我就不寫了,本人審美不行。