微信小程序開(kāi)發(fā) 入門(mén)介紹 及個(gè)人demo

轉(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)的操作。

  1. 獲取微信小程序的 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
  2. 創(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í)際效果。
  3. 編寫(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é)果如下:


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


    start_preview

個(gè)人demo

demo.png
  1. 構(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)。
  1. 初始化小程序
    我們需要初始化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,labelicontabbar他都建立了一個(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"
  ]
  1. 首頁(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)行處理
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í)行我們綁定的方法。那我們是怎么樣知道他可以綁定那些事件呢?我們可以看官方文檔的介紹:


bindTpye

以上是我從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ū)。


audio
  • 控制音樂(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ū)。

  1. 消息頁(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

轉(zhuǎn)載請(qǐng)注明出處, 謝謝! (~ o ~)Y

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容