轉(zhuǎn)載請(qǐng)注明出處, 謝謝! (~ o ~)Y
1月9日,也就是今天,微信推出的“小程序”正式上線?!靶〕绦颉笔且环N無(wú)需安裝,即可使用的手機(jī)“應(yīng)用”。不需要像往常一樣下載App,用戶在微信中“用完即走”。
目前,東方航空公司、美團(tuán)大眾點(diǎn)評(píng)、京東、新華社、今日頭條、滴滴出行、摩拜單車(chē)等公司都已經(jīng)各自研發(fā)并推出了“小程序”。
對(duì)于我們開(kāi)發(fā)者來(lái)說(shuō),在哪些地方使用,或者說(shuō)這個(gè)東西怎么樣,其實(shí)我們也不用過(guò)多去關(guān)注,我們只需要知道,老板讓我們做,我們就得學(xué)
po主因?yàn)閷?duì)微信小程序還是比較感興趣的,因?yàn)樵谶@一段時(shí)間也對(duì)微信小程序開(kāi)發(fā)有所研究,所以在這片文章中會(huì)給大家簡(jiǎn)單的介紹一下微信小程序的開(kāi)發(fā),讓大家有一個(gè)入門(mén)的認(rèn)識(shí)。
微信小程序開(kāi)發(fā)者文檔地址
這個(gè)就是微信的官方文檔的地址,大家可以在這里看到一些微信的官方介紹,為了方便懶癌晚期患者,我把一些我認(rèn)為重點(diǎn)的東西會(huì)粘貼在下面。
以下部分內(nèi)容截取自官方文檔
創(chuàng)建微信小程序
因?yàn)槲⑿判〕绦蚴腔谖⑿诺沫h(huán)境來(lái)開(kāi)發(fā)的,所以我們需要在騰訊那邊先創(chuàng)建一個(gè)微信小程序,才能進(jìn)行接下來(lái)的操作。
-
獲取微信小程序的 AppID
登錄 https://mp.weixin.qq.com ,就可以在網(wǎng)站的“設(shè)置”-“開(kāi)發(fā)者設(shè)置”中,查看到微信小程序的 AppID 了,注意不可直接使用服務(wù)號(hào)或訂閱號(hào)的 AppID 。
注意:如果要以非管理員微信號(hào)在手機(jī)上體驗(yàn)該小程序,那么我們還需要操作“綁定開(kāi)發(fā)者”。即在“用戶身份”-“開(kāi)發(fā)者”模塊,綁定上需要體驗(yàn)該小程序的微信號(hào)。本教程默認(rèn)注冊(cè)帳號(hào)、體驗(yàn)都是使用管理員微信號(hào)。
setting -
創(chuàng)建項(xiàng)目
我們需要通過(guò)開(kāi)發(fā)者工具,來(lái)完成小程序創(chuàng)建和代碼編輯。
開(kāi)發(fā)者工具安裝完成后,打開(kāi)并使用微信掃碼登錄。選擇創(chuàng)建“項(xiàng)目”,填入上文獲取到的 AppID ,設(shè)置一個(gè)本地項(xiàng)目的名稱(非小程序名稱),比如“我的第一個(gè)項(xiàng)目”,并選擇一個(gè)本地的文件夾作為代碼存儲(chǔ)的目錄,點(diǎn)擊“新建項(xiàng)目”就可以了。
為方便初學(xué)者了解微信小程序的基本代碼結(jié)構(gòu),在創(chuàng)建過(guò)程中,如果選擇的本地文件夾是個(gè)空文件夾,開(kāi)發(fā)者工具會(huì)提示,是否需要?jiǎng)?chuàng)建一個(gè) quick start 項(xiàng)目。選擇“是”,開(kāi)發(fā)者工具會(huì)幫助我們?cè)陂_(kāi)發(fā)目錄里生成一個(gè)簡(jiǎn)單的 demo。
new_project
項(xiàng)目創(chuàng)建成功后,我們就可以點(diǎn)擊該項(xiàng)目,進(jìn)入并看到完整的開(kāi)發(fā)者工具界面,點(diǎn)擊左側(cè)導(dǎo)航,在“編輯”里可以查看和編輯我們的代碼,在“調(diào)試”里可以測(cè)試代碼并模擬小程序在微信客戶端效果,在“項(xiàng)目”里可以發(fā)送到手機(jī)里預(yù)覽實(shí)際效果。 - 編寫(xiě)代碼
創(chuàng)建小程序?qū)嵗?/h4>
點(diǎn)擊開(kāi)發(fā)者工具左側(cè)導(dǎo)航的“編輯”,我們可以看到這個(gè)項(xiàng)目,已經(jīng)初始化并包含了一些簡(jiǎn)單的代碼文件。最關(guān)鍵也是必不可少的,是 app.js、app.json、app.wxss 這三個(gè)。其中,.js后綴的是腳本文件,.json后綴的文件是配置文件,.wxss后綴的是樣式表文件。微信小程序會(huì)讀取這些文件,并生成小程序?qū)嵗?/a>。
下面我們簡(jiǎn)單了解這三個(gè)文件的功能,方便修改以及從頭開(kāi)發(fā)自己的微信小程序。
app.js是小程序的腳本代碼。我們可以在這個(gè)文件中監(jiān)聽(tīng)并處理小程序的生命周期函數(shù)、聲明全局變量。調(diào)用框架提供的豐富的API,如本例的同步存儲(chǔ)及同步讀取本地?cái)?shù)據(jù)。想了解更多可用 API,可參考 API 文檔
//app.js
App({
onLaunch: function () {
//調(diào)用API從本地緩存中獲取數(shù)據(jù)
var logs = wx.getStorageSync('logs') || []
logs.unshift(Date.now())
wx.setStorageSync('logs', logs)
},
getUserInfo:function(cb){
var that = this;
if(this.globalData.userInfo){
typeof cb == "function" && cb(this.globalData.userInfo)
}else{
//調(diào)用登錄接口
wx.login({
success: function () {
wx.getUserInfo({
success: function (res) {
that.globalData.userInfo = res.userInfo;
typeof cb == "function" && cb(that.globalData.userInfo)
}
})
}
});
}
},
globalData:{
userInfo:null
}
})
app.json 是對(duì)整個(gè)小程序的全局配置。我們可以在這個(gè)文件中配置小程序是由哪些頁(yè)面組成,配置小程序的窗口?背景色,配置導(dǎo)航條樣式,配置默認(rèn)標(biāo)題。注意該文件不可添加任何注釋。更多可配置項(xiàng)可參考配置詳解
{
"pages":[
"pages/index/index",
"pages/logs/logs"
],
"window":{
"backgroundTextStyle":"light",
"navigationBarBackgroundColor": "#fff",
"navigationBarTitleText": "WeChat",
"navigationBarTextStyle":"black"
}
}
app.wxss 是整個(gè)小程序的公共樣式表。我們可以在頁(yè)面組件的 class 屬性上直接使用 app.wxss 中聲明的樣式規(guī)則。
/**app.wxss**/
.container {
height: 100%;
display: flex;
flex-direction: column;
align-items: center;
justify-content: space-between;
padding: 200rpx 0;
box-sizing: border-box;
}
創(chuàng)建頁(yè)面
在這個(gè)教程里,我們有兩個(gè)頁(yè)面,index 頁(yè)面和 logs 頁(yè)面,即歡迎頁(yè)和小程序啟動(dòng)日志的展示頁(yè),他們都在 pages 目錄下。微信小程序中的每一個(gè)頁(yè)面的【路徑+頁(yè)面名】都需要寫(xiě)在 app.json 的 pages 中,且 pages 中的第一個(gè)頁(yè)面是小程序的首頁(yè)。
每一個(gè)小程序頁(yè)面是由同路徑下同名的四個(gè)不同后綴文件的組成,如:index.js、index.wxml、index.wxss、index.json。.js后綴的文件是腳本文件,.json后綴的文件是配置文件,.wxss后綴的是樣式表文件,.wxml后綴的文件是頁(yè)面結(jié)構(gòu)文件。
- index.wxml 是頁(yè)面的結(jié)構(gòu)文件:
<!--index.wxml-->
<view class="container">
<view bindtap="bindViewTap" class="userinfo">
<image class="userinfo-avatar" src="{{userInfo.avatarUrl}}" background-size="cover"></image>
<text class="userinfo-nickname">{{userInfo.nickName}}</text>
</view>
<view class="usermotto">
<text class="user-motto">{{motto}}</text>
</view>
</view>
本例中使用了<view/>、<image/>、<text/>來(lái)搭建頁(yè)面結(jié)構(gòu),綁定數(shù)據(jù)和交互處理函數(shù)。
- index.js 是頁(yè)面的腳本文件,在這個(gè)文件中我們可以監(jiān)聽(tīng)并處理頁(yè)面的生命周期函數(shù)、獲取小程序?qū)嵗?,聲明并處理?shù)據(jù),響應(yīng)頁(yè)面交互事件等。
//index.js
//獲取應(yīng)用實(shí)例
var app = getApp()
Page({
data: {
motto: 'Hello World',
userInfo: {}
},
//事件處理函數(shù)
bindViewTap: function() {
wx.navigateTo({
url: '../logs/logs'
})
},
onLoad: function () {
console.log('onLoad')
var that = this
//調(diào)用應(yīng)用實(shí)例的方法獲取全局?jǐn)?shù)據(jù)
app.getUserInfo(function(userInfo){
//更新數(shù)據(jù)
that.setData({
userInfo:userInfo
})
})
}
})
- index.wxss 是頁(yè)面的樣式表:
/**index.wxss**/
.userinfo {
display: flex;
flex-direction: column;
align-items: center;
}
.userinfo-avatar {
width: 128rpx;
height: 128rpx;
margin: 20rpx;
border-radius: 50%;
}
.userinfo-nickname {
color: #aaa;
}
.usermotto {
margin-top: 200px;
}
頁(yè)面的樣式表是非必要的。當(dāng)有頁(yè)面樣式表時(shí),頁(yè)面的樣式表中的樣式規(guī)則會(huì)層疊覆蓋 app.wxss 中的樣式規(guī)則。如果不指定頁(yè)面的樣式表,也可以在頁(yè)面的結(jié)構(gòu)文件中直接使用 app.wxss 中指定的樣式規(guī)則。
- index.json 是頁(yè)面的配置文件:
頁(yè)面的配置文件是非必要的。當(dāng)有頁(yè)面的配置文件時(shí),配置項(xiàng)在該頁(yè)面會(huì)覆蓋 app.json 的 window 中相同的配置項(xiàng)。如果沒(méi)有指定的頁(yè)面配置文件,則在該頁(yè)面直接使用 app.json 中的默認(rèn)配置。 - logs 的頁(yè)面結(jié)構(gòu)
<!--logs.wxml-->
<view class="container log-list">
<block wx:for="{{logs}}" wx:for-item="log">
<text class="log-item">{{index + 1}}. {{log}}</text>
</block>
</view>
logs 頁(yè)面使用 <block/> 控制標(biāo)簽來(lái)組織代碼,在 <block/> 上使用 wx:for 綁定 logs 數(shù)據(jù),并將 logs 數(shù)據(jù)循環(huán)展開(kāi)節(jié)點(diǎn)
//logs.js
var util = require('../../utils/util.js')
Page({
data: {
logs: []
},
onLoad: function () {
this.setData({
logs: (wx.getStorageSync('logs') || []).map(function (log) {
return util.formatTime(new Date(log))
})
})
}
})
運(yùn)行結(jié)果如下:

-
手機(jī)預(yù)覽
開(kāi)發(fā)者工具左側(cè)菜單欄選擇"項(xiàng)目",點(diǎn)擊"預(yù)覽",掃碼后即可在微信客戶端中體驗(yàn)。
start_preview
個(gè)人demo

-
構(gòu)建框架
第一步,我們首先需要做的當(dāng)然是搭建整個(gè)項(xiàng)目,我的這個(gè)demo的項(xiàng)目結(jié)構(gòu)是這樣子的。
project
- 首先,就是創(chuàng)建項(xiàng)目時(shí)自帶的三個(gè)文件,
app.js,app.json,app.wxss,這三個(gè)文件的作用在上面已經(jīng)作了介紹,在這里我就簡(jiǎn)單說(shuō)說(shuō)我個(gè)人的理解。-
app.js相當(dāng)于程序的入口,在程序啟動(dòng)的時(shí)候會(huì)觸發(fā)小程序聲明周期的方法,如果你想要在小程序加載的時(shí)候做一些事情,比如說(shuō)登陸,讀取信息,可以在這里執(zhí)行相關(guān)的操作。
-
//app.js
App({
onLaunch: function () {
//調(diào)用API從本地緩存中獲取數(shù)據(jù)
var logs = wx.getStorageSync('logs') || []
logs.unshift(Date.now())
wx.setStorageSync('logs', logs)
},
getUserInfo: function (cb) {
var that = this
if (this.globalData.userInfo) {
typeof cb == "function" && cb(this.globalData.userInfo)
} else {
//調(diào)用登錄接口
wx.login({
success: function () {
wx.getUserInfo({
success: function (res) {
that.globalData.userInfo = res.userInfo
typeof cb == "function" && cb(that.globalData.userInfo)
}
})
}
})
}
},
globalData: {
userInfo: null
}
})
來(lái)自Jimmy-簡(jiǎn)書(shū)。
這里我沒(méi)有做處理,還是用的系統(tǒng)默認(rèn)生成的代碼。
* app.json相當(dāng)于程序的配置文件,告訴程序,你需要加載哪些頁(yè)面,然后tabbar的結(jié)構(gòu)是怎么樣的,所以如果開(kāi)發(fā)工具報(bào)錯(cuò)提示說(shuō)找不到xxx文件,你就可以來(lái)app.json里面看一下你填寫(xiě)的文件路徑和名字有沒(méi)有寫(xiě)錯(cuò)。
/**app.json**/
{
"tabBar": {
"color": "#dddddd",
"selectedColor": "#1296db",
"borderStyle": "white",
"backgroundColor": "#ffffff",
"list": [
{
"pagePath": "pages/index/index",
"text": "首頁(yè)",
"iconPath": "images/tabbar/camera.png",
"selectedIconPath": "images/tabbar/camera_hl.png"
},
{
"pagePath": "pages/message/message",
"text": "消息",
"iconPath": "images/tabbar/bubble.png",
"selectedIconPath": "images/tabbar/bubble_hl.png"
},
{
"pagePath": "pages/myLove/myLove",
"text": "收藏",
"iconPath": "images/tabbar/star.png",
"selectedIconPath": "images/tabbar/star_hl.png"
}
]
},
"pages": [
"pages/index/index",
"pages/logs/logs",
"pages/message/message",
"pages/myLove/myLove"
],
"window": {
"backgroundTextStyle": "light",
"navigationBarBackgroundColor": "#fff",
"navigationBarTitleText": "J&M..",
"navigationBarTextStyle": "black"
}
}
* `app.wxss`其實(shí)就是類(lèi)似`.css`文件,就是小程序全局的樣式表。
/**app.wxss**/
.container {
height: 100%;
display: flex;
flex-direction: column;
align-items: center;
justify-content: space-between;
padding: 200 rpx 0;
box-sizing: border-box;
}
- pages 文件夾就是我們需要重點(diǎn)關(guān)注的文件夾,里面包含著每一個(gè)模塊,我建議大家按模塊來(lái)新建好文件夾,然后在各自的模塊做各自的事情。
- 最上面 images 文件夾用來(lái)存放項(xiàng)目一些本地相關(guān)的圖片(不過(guò)demo中的),當(dāng)然,里面你還可以分子文件夾用來(lái)歸類(lèi)。
- 初始化小程序
我們需要初始化tabbar,還有設(shè)置各個(gè)頁(yè)面的數(shù)據(jù)。
其實(shí)初始化tabbar,我們已經(jīng)在app.json里面做了,現(xiàn)在來(lái)帶大家回顧一下
"tabBar": {
"color": "#dddddd",
"selectedColor": "#1296db",
"borderStyle": "white",
"backgroundColor": "#ffffff",
"list": [
{
"pagePath": "pages/index/index",
"text": "首頁(yè)",
"iconPath": "images/tabbar/camera.png",
"selectedIconPath": "images/tabbar/camera_hl.png"
},
{
"pagePath": "pages/message/message",
"text": "消息",
"iconPath": "images/tabbar/bubble.png",
"selectedIconPath": "images/tabbar/bubble_hl.png"
},
{
"pagePath": "pages/myLove/myLove",
"text": "收藏",
"iconPath": "images/tabbar/star.png",
"selectedIconPath": "images/tabbar/star_hl.png"
}
]
}
app.json里面的這一段代碼就是初始化tabbar的,tabbar是小程序自帶的一個(gè)組件。
ps:小程序是組件化開(kāi)發(fā),就是他內(nèi)部已經(jīng)封裝好了許多組件,比如常用的button,label,icon,tabbar他都建立了一個(gè)組件庫(kù),這樣子給我們自定義的空間就很少了,但是這樣子的好處是使用簡(jiǎn)單,然后風(fēng)格比較統(tǒng)一,就比較符合張小龍的理念。
設(shè)置各個(gè)頁(yè)面的數(shù)據(jù),也是在app.json里面,設(shè)置了路徑,就會(huì)找到對(duì)應(yīng)目錄下的js文件來(lái)進(jìn)行page的初始化。
"pages": [
"pages/index/index",
"pages/logs/logs",
"pages/message/message",
"pages/myLove/myLove"
]
- 首頁(yè)
首頁(yè)我想制作的是一個(gè)混搭的界面,上面是一個(gè)簡(jiǎn)單的圖片輪播器,然后中間是一個(gè)自定義的音樂(lè)播放界面,最下面的是幾個(gè)按鈕用來(lái)控制音樂(lè)播放器的工作的。
來(lái)自Jimmy-簡(jiǎn)書(shū)。
- 圖片輪播器
微信小程序提供了官方的組件swiper滑塊視圖容器可以很簡(jiǎn)單地做出來(lái)一個(gè)圖片輪播的效果。微信小程序也還是用的MVC為主要思想來(lái)進(jìn)行相應(yīng)代碼邏輯功能的實(shí)現(xiàn)。- 首先是數(shù)據(jù),類(lèi)似模型,微信小程序?qū)?yīng)模塊的數(shù)據(jù)都是放在對(duì)應(yīng)文件夾下的
.js文件下的data屬性來(lái)進(jìn)行數(shù)據(jù)的設(shè)置。所以輪播器的數(shù)據(jù)源自然也要放在這里進(jìn)行處理
- 首先是數(shù)據(jù),類(lèi)似模型,微信小程序?qū)?yīng)模塊的數(shù)據(jù)都是放在對(duì)應(yīng)文件夾下的
Page({
data: {
imgUrls: [{
img: "../../images/scroll/IMG_01.jpg"
}, {
img: "../../images/scroll/IMG_02.jpg"
}, {
img: "../../images/scroll/IMG_03.jpg"
}],
indicatorDots: true,
autoplay: true,
interval: 3000,
duration: 1000
}
})
* 數(shù)據(jù)源弄好了,我們就要去處理View了,而View的處理是放在對(duì)應(yīng)模塊的`.wxml`模塊處理的,這一塊其實(shí)也就是相當(dāng)于用h5語(yǔ)法的`.html`文件,我已經(jīng)在代碼寫(xiě)了相應(yīng)的注釋了,應(yīng)該很容易看懂。
<!--view容器 -->
<view class="section section_gap swiper">
<!--swiper組件 -->
<swiper indicator-dots="{{indicatorDots}}" vertical="{{vertical}}"
autoplay="{{autoplay}}" interval="{{interval}}" duration="{{duration}}">
<!--block控制循環(huán)從data里面的imgUrls里面讀取類(lèi),這個(gè)名字和data里面的要一致 -->
<block wx:for-items="{{imgUrls}}">
<!--每次循環(huán)創(chuàng)建一個(gè)swiper-item組件-->
<swiper-item>
<!--組件里面創(chuàng)建image組件,路徑讀取類(lèi)里面的img屬性-->
<image src="{{item.img}}" class="slide-image"/>
</swiper-item>
</block>
</swiper>
</view>
* 最后,我們需要處理類(lèi)似Controller的功能。
嗯,就是不用處理,這就是組件化的好處。如果我們對(duì)組件樣式?jīng)]有要求,也不做圖片點(diǎn)擊的處理的話。我們就不需要做一些邏輯方面的處理,data和view來(lái)展示就夠了。如果你想要加點(diǎn)擊圖片跳轉(zhuǎn)的邏輯,可以在.wxml里面添加圖片點(diǎn)擊綁定方法,然后在.js里面處理對(duì)應(yīng)跳轉(zhuǎn)的方法邏輯。
來(lái)自Jimmy-簡(jiǎn)書(shū)。
-
音樂(lè)播放器和進(jìn)度條
首先,官方的音樂(lè)播放器組件的樣式是醬紫的:
audio
就是我們做的播放器的上班部分,很簡(jiǎn)單,就是調(diào)用官方的組件就可以了。
所以我們需要做的就是添加下面的進(jìn)度條和時(shí)間,然后把他和音樂(lè)組件關(guān)聯(lián)起來(lái)就可以了,這就是我們需要做的事。- 首先還是要處理數(shù)據(jù),我們需要屬性記錄音樂(lè)播放器的播放路徑,還有封面圖片,名字,還有時(shí)間等要素,所以還是需要在前面data里面補(bǔ)充寫(xiě)入相關(guān)數(shù)據(jù),因?yàn)槲覜](méi)有做服務(wù)器,所以目前先寫(xiě)死。
data: {
// 圖片輪播器
imgUrls: [{
img: "../../images/scroll/IMG_01.jpg"
}, {
img: "../../images/scroll/IMG_02.jpg"
}, {
img: "../../images/scroll/IMG_03.jpg"
}
],
indicatorDots: true,
autoplay: true,
interval: 3000,
duration: 1000,
// 音樂(lè)播放器
poster: "http://d.hiphotos.baidu.com/baike/c0%3Dbaike80%2C5%2C5%2C80%2C26/sign=abfe5f62f3f2b211f0238d1cabe90e5d/fd039245d688d43f3c52a8e3751ed21b0ef43b23.jpg",
musicSrc: "http://qqma.tingge123.com:83/123/2016/10/周杰倫%20-%20告白氣球.mp3",
name: '告白氣球',
author: '周杰倫',
sliderValue: 0,
minTime: 0,
maxTime: 100,
minMin: '00:00',
maxMin: '00:00',
},
* 接著我們需要來(lái)處理View相關(guān)的界面。
<!--音樂(lè)播放組件-->
<audio poster="{{poster}}" name="{{name}}" author="{{author}}"
src="{{musicSrc}}" action="{{action}}"
bindtimeupdate="bindTimeUpdate" controls loop>
</audio>
<!--進(jìn)度條及時(shí)間-->
<view class="section section_gap">
<view class="body-view">
<!--當(dāng)前時(shí)間-->
<view class="minTime">
<text class="minMin">{{minMin}}</text>
</view>
<!--進(jìn)度條-->
<slider class="slider" value="{{sliderValue}}" bindchange="sliderChange" min="{{minTime}}" max="{{maxTime}}"/>
<!--最大時(shí)間-->
<view class="maxTime" text="{{minMin}}">
<text class="maxMin">{{maxMin}}</text>
</view>
</view>
</view>
然后是slider時(shí)間滑動(dòng)條的wxss布局
來(lái)自Jimmy-簡(jiǎn)書(shū)。
/*Slider*/
.body-view{
display: flex;
align-items: center;
}
.slider{
flex:1;
}
.minTime{
flex: 0 0 10%;
height: 25px;
}
.maxTime{
flex: 0 0 10%;
height: 25px;
}
.minMin{
font-size: 12px;
}
.maxMin{
font-size: 12px;
}
* View處理完了,接下來(lái)我們就需要寫(xiě)類(lèi)似Controller的邏輯了,這些代碼我是放在`.js`文件里面處理的。
我們?cè)赼udio組件上面綁定了播放進(jìn)度改變觸發(fā)事件,大家可以仔細(xì)看wxml里面的代碼,綁定了這些時(shí)間,當(dāng)系統(tǒng)執(zhí)行那些操作的時(shí)候,就類(lèi)似代理,會(huì)自動(dòng)執(zhí)行我們綁定的方法。那我們是怎么樣知道他可以綁定那些事件呢?我們可以看官方文檔的介紹:

以上是我從audio官方截取下來(lái)的audio官方支持綁定的事件,我們只需要在wxml里面的組件里面的屬性帶上這些,然后在后面執(zhí)行方法,就可以綁定事件了。
<audio poster="{{poster}}" name="{{name}}" author="{{author}}" src="{{musicSrc}}" action="{{action}}"
bindtimeupdate="bindTimeUpdate" controls loop></audio>
綁定完事件,就可以在.js文件處理邏輯了。與data平級(jí),添加事件。
bindTimeUpdate: function (audio) {
// 通過(guò)audio的屬性秒數(shù)計(jì)算當(dāng)前分鐘和秒數(shù)
let currentMin = Math.floor(audio.detail.currentTime / 60);
var currentSec = Math.floor(audio.detail.currentTime % 60);
// 異常處理
if (currentSec < 10) {
currentSec = "0" + currentSec;
}
if (currentMin < 10) {
currentMin = "0" + currentMin;
}
// 拼接
var currentTime = currentMin + ":" + currentSec;
let maxMin = Math.floor(audio.detail.duration / 60);
var maxSec = Math.floor(audio.detail.duration % 60);
if (maxSec < 10) {
maxSec = "0" + maxSec;
}
if (maxMin < 10) {
maxMin = "0" + maxMin;
}
var maxTime = maxMin + ":" + maxSec;
// 重新賦值data,然后小程序就會(huì)根據(jù)data讀取數(shù)據(jù),自動(dòng)更新UI
this.setData({
minMin: currentTime,
maxMin: maxTime,
sliderValue: audio.detail.currentTime,
maxTime: audio.detail.duration
})
},
這樣子就可以當(dāng)音樂(lè)播放的時(shí)候自動(dòng)顯示當(dāng)前時(shí)間和最大時(shí)間,而且進(jìn)度條會(huì)自動(dòng)前進(jìn),可是還有一個(gè)小問(wèn)題,當(dāng)我們拖動(dòng)進(jìn)度條的時(shí)候,不能繼續(xù)在我們拖動(dòng)的地方進(jìn)行播放。所以就要處理slider的綁定事件了。
<slider class="slider" value="{{sliderValue}}" bindchange="sliderChange" min="{{minTime}}" max="{{maxTime}}"/>
我在slider上也綁定了一個(gè)事件,只需要寫(xiě)入下面的代碼就可以執(zhí)行拖動(dòng)更新事件了。
sliderChange: function (slider) {
this.audio14(slider.detail.value);
},
audio14: function (time) {
this.setData({
action: {
method: 'setCurrentTime',
data: time
}
});
},
至此,自定義音樂(lè)播放器已經(jīng)完成。
來(lái)自Jimmy-簡(jiǎn)書(shū)。

- 控制音樂(lè)播放器的按鈕
其實(shí)這一步的東西屬于未完成,因?yàn)橹皇莻€(gè)人構(gòu)想,還沒(méi)有成熟的UI,沒(méi)有把這些東西整合到音樂(lè)播放器里面,只是寫(xiě)了簡(jiǎn)單的實(shí)現(xiàn),所以現(xiàn)在來(lái)跟大家分享一下,因?yàn)楸容^簡(jiǎn)單,所以我只貼代碼了。相信大家聽(tīng)我啰嗦了這么久,一定能看懂了。
<!--index.wxml-->
<button type="primary" bindtap="audioPlay">播放</button>
<button type="primary" bindtap="audioPause">暫停</button>
<button type="primary" bindtap="audioPlaybackRateSpeedUp">調(diào)為2倍速</button>
<button type="primary" bindtap="audioPlaybackRateNormal">調(diào)為1倍速</button>
<button type="primary" bindtap="audioPlaybackRateSlowDown">調(diào)為0.5倍速</button>
<button type="primary" bindtap="audioNext">下一曲</button>
<button type="primary" bindtap="audioStart">回到開(kāi)頭</button>
//index.js
audioPlay: function () {
this.setData({
action: {
method: 'play'
}
});
},
audioPause: function () {
this.setData({
action: {
method: 'pause'
}
});
},
audioPlaybackRateSpeedUp: function () {
this.setData({
action: {
method: 'setPlaybackRate',
data: 2
}
});
},
audioPlaybackRateNormal: function () {
this.setData({
action: {
method: 'setPlaybackRate',
data: 1
}
});
},
audioPlaybackRateSlowDown: function () {
this.setData({
action: {
method: 'setPlaybackRate',
data: 0.5
}
});
},
audioNext: function () {
this.setData({
action: {
method: 'pause'
}
});
},
audioStart: function () {
this.setData({
action: {
method: 'setCurrentTime',
data: 0
}
});
},
至此,首頁(yè)全部完成。
來(lái)自Jimmy-簡(jiǎn)書(shū)。
- 消息頁(yè)面
消息頁(yè)面我還沒(méi)有徹底完成,只是一個(gè)構(gòu)想,這個(gè)做的比較不一樣的一步就是獲取用戶信息了。
<view bindtap="bindViewTap" class="userinfo">
<image class="userinfo-avatar" src="{{userInfo.avatarUrl}}" background-size="cover"></image>
<text class="userinfo-nickname">{{userInfo.nickName}}</text>
</view>
view里面綁定了點(diǎn)擊事件,用來(lái)跳轉(zhuǎn)頁(yè)面,然后頭像的路徑用全局的userInfo讀取userInfo.avatarUrl屬性,名字讀取userInfo.nickName
//index.js
onLoad: function () {
console.log('onLoad')
var that = this
//調(diào)用應(yīng)用實(shí)例的方法獲取全局?jǐn)?shù)據(jù)
app.getUserInfo(function(userInfo){
//更新數(shù)據(jù)
that.setData({
userInfo:userInfo
})
})
}
然后在一開(kāi)始登陸自動(dòng)生成的app.js代碼,給我們做了用戶信息的讀取,帶大家回顧一下
//app.js
App({
onLaunch: function () {
//調(diào)用API從本地緩存中獲取數(shù)據(jù)
var logs = wx.getStorageSync('logs') || []
logs.unshift(Date.now())
wx.setStorageSync('logs', logs)
},
getUserInfo: function (cb) {
var that = this
if (this.globalData.userInfo) {
typeof cb == "function" && cb(this.globalData.userInfo)
} else {
//調(diào)用登錄接口
wx.login({
success: function () {
wx.getUserInfo({
success: function (res) {
that.globalData.userInfo = res.userInfo
typeof cb == "function" && cb(that.globalData.userInfo)
}
})
}
})
}
},
globalData: {
userInfo: null
}
})
然后處理的是點(diǎn)擊頭像跳轉(zhuǎn)頁(yè)面事件
//跳轉(zhuǎn)事件處理函數(shù)
bindViewTap: function() {
wx.navigateTo({
url: '../logs/logs'
})
},
然后這個(gè)簡(jiǎn)單的微信小程序demo已經(jīng)完成,然后第一次寫(xiě)微信小程序的開(kāi)發(fā)文章,如果有什么遺漏的地方,歡迎大家跟帖補(bǔ)充,謝謝。
最后 再來(lái)一遍github Demo地址 (??????)??
https://github.com/JimmyPeng4iOS/WxDemo




