本文目錄:
- 1.云開發(fā)的優(yōu)勢
- 2.云開發(fā)的五大基礎能力
- 3.基本結構分析:
- 4.寫輪播圖
- 5.組件化開發(fā)流程
- 6.數(shù)據(jù)監(jiān)聽器observers
- 7.異步操作解決方案
- 8.小程序中怎樣使用async函數(shù)
- 9.第一個云函數(shù)getPlaylist
- 10.小程序端調用云函數(shù)
- 11.云函數(shù)獲取數(shù)據(jù)庫中的大于100條的數(shù)據(jù)
- 12.小程序端調用云函數(shù)
- 13.tcb-router
- 14.本地數(shù)據(jù)存儲
- 15.音樂播放的控制
- 16.如何實現(xiàn)組件間傳值
- 17.給小程序設置全局屬性和方法
1.云開發(fā)的優(yōu)勢
正常的開發(fā)分為前端和后端
傳統(tǒng)的小程序開發(fā)完成之后需要進行一個上線部署,而傳統(tǒng)部署的基本步驟有:購買服務器、域名,備案,網(wǎng)絡防護,負載均衡,監(jiān)控警告等。這些事情非常的繁瑣,讓人頭疼。

小程序云開發(fā),弱化了后端和運維的工作,不需要搭建服務器。
云開發(fā)賦予了開發(fā)者穩(wěn)定,安全的讀取數(shù)據(jù),上傳文件的能力。

serverless=》無服務開發(fā)=》小程序的云開發(fā)
在云開發(fā)的核心理念中,函數(shù)即服務,依托騰訊端提供的后端服務,我們通過函數(shù)就可以實現(xiàn)調用,從而實現(xiàn)serverless
2.云開發(fā)的五大基礎能力
- 1.云函數(shù):在云端運行代碼,并且具有天然的鑒權機制。
- 2.云數(shù)據(jù)庫:既可以在云函數(shù)端操作,又可以在小程序端操作的非關系型json數(shù)據(jù)庫(類似moongodb)
- 3.云調用:基于云函數(shù)免鑒權使用小程序開放接口的能力
- 4.HTTP API:可以讓第三方服務很方便的在已有服務器上訪問云資源,實現(xiàn)與云開發(fā)的互通。
- 5.云存儲:在云端存儲文件,可以在云端控制臺可視化管理
我們可以通過云函數(shù)去定期的去第三方數(shù)據(jù)服務器拿數(shù)據(jù),然后更新到云數(shù)據(jù)庫中
1.什么是小程序的云開發(fā)?
傳統(tǒng)模式:小程序端展現(xiàn)的數(shù)據(jù)是發(fā)請求給后端拿到的
云開發(fā)模式:小程序端提供的原生接口可以直接去操作遠程的云數(shù)據(jù)庫,云函數(shù),云存儲。而我們根本根本不知道后端部署在那里。
2.什么是serverless?
打破前端和后端的物理隔離
當我們使用后端服務的時候,不需要關注后端的ip地址是什么等等
在小程序官網(wǎng)上注冊賬號,然后下載開發(fā)者工具,打開開發(fā)者工具,創(chuàng)建一個新項目。
需要注意一點,APPID是每一個小程序的唯一標識,這個ID在官網(wǎng)賬號中的“開發(fā)”界面可以查看到。
進入項目之后,第一次使用云開發(fā)的用戶需要點擊界面上方的“云開發(fā)”按鈕去開通服務。
首先可以選擇創(chuàng)建一個test作為開發(fā)環(huán)境的云服務,等到項目上線再創(chuàng)建一個生產(chǎn)環(huán)境進行使用。
3.基本結構分析:
cloudfunctions=》云函數(shù)部分
miniprogram=》前端部分代碼
- images圖片資源
- pages創(chuàng)建小程序的時候自帶文件夾和文件(可以全部刪除)
- style創(chuàng)建小程序的時候自帶樣式(可以全部刪除)

app.js全局js文件
onLaunch:function(){}
當小程序啟動的時候觸發(fā)的鉤子函數(shù)
wx.cloud.init({ env:"在此處填入環(huán)境ID",
這個地方填入的是哪個ID,小程序自動連接的就是對應的環(huán)境,先填開發(fā)環(huán)境,上線的時候把這個地方改成生產(chǎn)環(huán)境就可以了。
traceUser: true
設置為true的時候,每一個訪問過我們的小程序的用戶都會被記錄,并且以倒序的順序進行顯示
})
app.json全局配置文件
pages
//文件的路徑
window
//窗口的一些配置(頁面的最上方)
“sitemapLocation”:sitemap.json
//小程序開放的內部搜索,對應的配置文件sitemap.json,決定了我們的小程序界面是否能被搜索到,在小程序優(yōu)化中可以用到
tabBar
//小程序封裝的一個對象,有color,selectedColor,list等常用屬性。
//對應的小程序頁面下方的導航,最少兩個,最多五個
app.wxss全局樣式
README.md小程序的開發(fā)說明
project.config小程序項目的配置文件,突出為整個項目
iconfont下載圖標很方便,可以自由選擇格式,大小,以及顏色(點擊下載,直接下載到本地就可以直接使用了)
把style文件夾中的guide.wxss和app.wxss中的小程序自帶樣式都去除掉,樣式都是我們自定義
寫最初的幾個主頁面:
先在app.json中的“pages”中把框架自帶的頁面全部刪除,然后加上自己要寫的幾個頁面路徑,保存之后在對應的路徑就會自動生成頁面文件。(手動把框架自帶的頁面文件刪除掉)
4.寫輪播圖
小程序原生自帶swiper組件,里面的項目swiper-item,在swiper-item里放image標簽
小程序自帶的block標簽,建議把wx:for寫在block上面,block不會真實渲染,在輪播圖這里我們在swiper-item外面包裹一層block,然后wx:for渲染寫在block標簽上
swiper的常用屬性:
- indicator-dots="true",顯示導航的小點,默認為flase
- autoplay=“true”自動播放
- interval=“2000”自動播放的間隔是2000ms
- duration=”1000“滑動播放時長為1000ms
小程序自帶的image標簽的常用屬性
- mode=”scaleToFill“,保證圖片完全覆蓋當前image容器,這種縮放模式下圖片非常有可能會產(chǎn)生變形,實際效果不好
- mode=”aspectFit“,讓圖片能夠完整的顯示在容器中,缺點是有可能會讓容器留白
- mode=”widthFix“,讓圖片能夠完全覆蓋容器,同時保持圖片的寬高比不變,同時給image標簽增加width100%height100%的樣式,保證image能夠完整覆蓋父元素。這個縮放模式是實際項目中最常用的。
5.組件化開發(fā)流程
組件:在用戶界面開發(fā)領域,組件是一種面向用戶的,獨立的,可復用的交互元素的封裝。
組件的組成:
結構=》wxml
邏輯=》js
樣式=》wxss
組件的設計原理:高內聚,低耦合,單一職責,避免過多參數(shù)
封裝第一個組件:歌曲列表組件
1.創(chuàng)建
首先在項目的miniprogram文件夾下新建一個文件夾components,然后在components中右鍵創(chuàng)建對應的組件(這里是playlist)
2.在頁面中引用和使用
在頁面的json中進行引用
{
"usingComponents": {
"x-playlist": "/components/playlist/playlist"
},
"enablePullDownRefresh":true
}
在頁面的wxml中進行使用
3.傳遞數(shù)據(jù),這里想把頁面中的歌曲數(shù)據(jù)playlist傳遞給組件
<view class="playlist-container">
<block wx:for="{{playlist}}" wx:key="_id">
<x-playlist playlist="{{item}}"></x-playlist>
</block>
</view>
4.組件接收頁面?zhèn)鬟f過來的數(shù)據(jù)
在組件的js文件中使用properties進行接收(需要指定所接收到的數(shù)據(jù)的類型,不指定的話會報錯)
properties: {
// 接收父組件傳遞的參數(shù),并規(guī)定參數(shù)的類型
playlist: {
type: Object
}
},
5.組件在wxml就可以使用接收到的數(shù)據(jù)(渲染數(shù)據(jù))
<image src="{{playlist.picUrl}}" class="playlist-img"></image>
在小程序中的背景圖片只能使用本地圖片,不允許使用網(wǎng)絡圖
如何把小圖片轉換成base64?在百度上搜索“在線制作base64”,很多網(wǎng)站都可以轉換
6.數(shù)據(jù)監(jiān)聽器observers
監(jiān)聽對象下的屬性,和接受父組件傳遞參數(shù)的properties在同一級。
['對象.屬性']
監(jiān)聽到的值不能直接用this.setData賦給對象的屬性本身,這樣會陷入數(shù)據(jù)監(jiān)聽死循環(huán)
解決方法:在組件的內部重新定義一個數(shù)據(jù)進行賦值。
// 數(shù)據(jù)監(jiān)聽器
observers: {
// 監(jiān)聽對象下面的屬性
['playlist.playCount'](count) {
this.setData({
_count: this._tranNumber(count, 2)
})
}
},
巧妙的去除數(shù)字后面的小數(shù)點
let numStr = num.toString().split('.')[0]
小程序對于wx:for循環(huán)提供了一個wx:key=“*this”,其中*this代表的就是元素本身=====>對于循環(huán)的純數(shù)組而言,如果循環(huán)的是對象數(shù)組,則可以直接綁定對象中的唯一屬性,如id,在不寫別名的情況下,小程序會自動識別循環(huán)的每個對象下的id屬性,并且進行綁定。
注意:在循環(huán)出來的對象不會動態(tài)變化的情況下,key值可以綁定的隨意些,否則必須要綁定足夠有辨識度的唯一標識,否則小程序無法識別元素的動態(tài)變化。
7.異步操作解決方案
傳統(tǒng)的回調地獄式異步編程寫法:
setTimeout(() => {
console.log(1)
setTimeout(() => {
console.log(2)
setTimeout(() => {
console.log(3)
}, 3000);
}, 2000);
}, 1000);
promise是es6的異步操作解決方案,字面意思就是承諾,promise有三個狀態(tài),pending代表等待,fulfilled代表成功,rejected代表失敗,狀態(tài)一旦改變,則無法回退。
上面的異步操作的promise版本寫法
new Promise((resolve,reject)=>{
setTimeout(() => {
console.log(1)
resolve()
}, 1000);
}).then((res)=>{
setTimeout(() => {
console.log(2)
resolve()
}, 2000);
}).then((res)=>{
setTimeout(() => {
console.log(3)
resolve()
}, 3000);
})
8.小程序中怎樣使用async函數(shù)
es7的異步操作解決方案:async和await
云函數(shù)默認支持es7語法,但是小程序開發(fā)環(huán)境還不行,所以要想在小程序端歡快的使用es7語法,則首先需要解決環(huán)境問題。
把 regenerator/runtime.js 文件引用到有使用 async/await 的文件當中。
import regeneratorRuntime from '../../utils/runtime.js'
注意:regeneratorRuntime必須叫這個名字,不能自定義
普通函數(shù)沒有寫renturn則沒有返回值,而async函數(shù)的返回值是一個promise對象
onLoad:function(options){
this.foo()
}
async foo(){
console.log('foo')
//await一定要async函數(shù)里面才能發(fā)揮正常作用
let res = await this.timeout()
console.log(res)
},
timeout(){
return new Promise((resolve,reject) => {
setTimeout(()=>{
console.log(1)
resolve('resolved')
},1000)
})
}
執(zhí)行結果
foo
1
resolved
9.第一個云函數(shù)getPlaylist
getPlaylist這個云函數(shù)我們首先需要安裝三個依賴,發(fā)請求拿數(shù)據(jù)用的
在cloudfunctions文件夾中新建一個getPlaylist文件夾,然后在這個文件夾下打開終端命令行工具,輸入npm init -y將getPlaylist初始化為一個npm管理下的項目,然后一次安裝下面這三個依賴
npm install --save request
npm install --save request-promise
npm install --save wx-server-sdk@latest
在getPlaylist文件夾下引入
const rp = require('request-promise')
然后開始寫發(fā)請求的代碼
exports.main = async(event, context) => {
const playlist = await rp(URL).then((res) => {
return JSON.parse(res).result
})
}
如果要在云函數(shù)中打印一些數(shù)據(jù)用來調試,但是這個打印信息不會顯示在調試器中,因為調試器屬于前端工具,而云函數(shù)屬于后端部分的代碼。所以我們可以先上傳并部署:云端安裝依賴(不上傳node_modules)
云函數(shù)調試位置:云開發(fā)=》云函數(shù)=》云端測試,當前這個請求不需要參數(shù),把默認的參數(shù)清空,然后“運行測試”就可以在下面看到測試的結果了。
返回結果是null是因為當前的getPlaylist云函數(shù)并沒有寫返回值。
注意:在云函數(shù)中的任何一處修改要想生效 都需要進行上傳和部署。
至此,我們已經(jīng)在云函數(shù)中拿到了想要的歌單信息數(shù)據(jù)playlist ,接下來要把這個數(shù)據(jù)插入到數(shù)據(jù)庫中,首先需要在數(shù)據(jù)庫中“創(chuàng)建集合”,集合名稱定義為playlist,往數(shù)據(jù)庫中插入數(shù)據(jù)只能一條一條的插入。
10.云函數(shù)往數(shù)據(jù)庫插入不重復的數(shù)據(jù)
給數(shù)據(jù)庫插入信息之前需要先在getPlaylist云函數(shù)中初始化數(shù)據(jù)庫
const db = cloud.database()
接下來調用數(shù)據(jù)庫,往playlist集合中插入數(shù)據(jù),并且同時插入一個cerateTime字段,記錄數(shù)據(jù)產(chǎn)生的時間。
serverDate獲取當前服務器的時間
for (let i = 0,len = playlist; i < len; i++) {
await db.collection('playlist').add({
data: {
...playlist[i],
createTime: db.serverDate(),
}
}).then((res) => {
console.log('插入成功')
}).catch((err) => {
console.error('插入失敗')
})
}
上面這段代碼有一個明顯的問題,那就是當多次讀取數(shù)據(jù)的時候,重復的歌單信息就會被多次添加,所以每次讀取歌單信息都應該和數(shù)據(jù)庫當前已有的歌單信息進行對比,相同的信息不會被重復添加。
首先定義一個list,先獲取歌單信息已有的信息,存儲在list變量中
const list = await db.collection('playlist').get()
然后將list和playlist對比去重,將不重復的數(shù)據(jù)放置到newData變量中。
定義一個flag,true代表默認的“不重復”
const newData = []
for (let i = 0, len1 = playlist.length; i < len1; i++) {
let flag = true
for (let j = 0, len2 = list.data.length; j < len2; j++) {
if (playlist[i].id === list.data[j].id) {
flag = false
break
}
}
if (flag) {
newData.push(playlist[i])
}
}
這樣一開始插入的數(shù)據(jù)也要從playlist變?yōu)楝F(xiàn)在的不重復數(shù)據(jù)形成的數(shù)組newData
11.云函數(shù)獲取數(shù)據(jù)庫中的大于100條的數(shù)據(jù)
現(xiàn)在還遺留一個問題就是在云函數(shù)中獲取數(shù)據(jù)中的信息,只能獲取100條,在小程序代碼中最多只能獲取到20條。所以現(xiàn)在我們需要突破100條這個限制。
解決思路:假如有210條數(shù)據(jù),分三次請求,最后再把這三次請求拿到的數(shù)據(jù)進行匯總,就可以獲得全部的數(shù)據(jù)。
全部數(shù)據(jù)list不能通過const list = await db.collection('playlist').get()簡單獲得,需要進行下面的優(yōu)化:
首先需要獲得當前數(shù)據(jù)總的條數(shù)
const countResult = await db.collection('playlist').count()
countResult拿到的是一個對象,其中的total屬性對應的數(shù)據(jù)的數(shù)量。
·const total = countResult.total·
定義每次取數(shù)據(jù)的數(shù)量
const MAX_LIMIT = 100
求出應該取幾次數(shù)據(jù)
const batchTimes = Math.ceil(total / MAX_LIMIT)
需要等待幾次拿數(shù)據(jù)的請求完成完成后才能拼裝出真正完整的數(shù)據(jù)。
const tasks = []
for (let i = 0; i < batchTimes; i++) {
let promise = db.collection('playlist').skip(i * MAX_LIMIT).limit(MAX_LIMIT).get()
tasks.push(promise)
}
let list = {
data: []
}
if (tasks.length > 0) {
list = (await Promise.all(tasks)).reduce((acc, cur) => {
return {
data: acc.data.concat(cur.data)
}
})
}
剛才所寫的從指定的音樂接口拿數(shù)據(jù),然后將數(shù)據(jù)插入數(shù)據(jù)庫的操作,我們希望能夠在云函數(shù)中定時自動觸發(fā)。
需要在對應的云函數(shù)文件夾中新建一個config.json文件
配置好之后一定要右鍵云函數(shù)文件夾,“上傳觸發(fā)器”,這樣觸發(fā)器才能生效。
config.json文件名是規(guī)定好的,不能改。myTrigger是自定義的觸發(fā)器名稱。
{
"triggers":[
{
"name":"myTrigger",
"type":"timer",
"config":"0 0 10,14,16,23 * * * *"
}
]
}
12.小程序端調用云函數(shù)
接下來就是小程序端讀取數(shù)據(jù),并且把數(shù)據(jù)渲染到頁面上。
我們新創(chuàng)建一個music云函數(shù)“新建Nodejs云函數(shù)”,然后在這個music云函數(shù)中寫調用數(shù)據(jù)庫,獲取數(shù)據(jù)的邏輯代碼。
skip和limit方便我們獲取指定條數(shù)的數(shù)據(jù)以及進行分頁。
orderBy表示排序,第一個參數(shù)是排序依據(jù)的字段名稱,第二個參數(shù)‘desc’代表逆序。
return await cloud.database()
.collection('playlist')
.skip(event.start).limit(event.count)
.orderBy('createTime','desc')
.get().then((res)=>{return res})
接下來在小程序界面的js文件中請求云函數(shù)music,取第0-15條數(shù)據(jù)
wx.cloud.callFunction({
name:'music',
data:{
start:0,
count:15
}
}).then((res) => {
this.setData({
playlist: this.data.playlist.concat(res.result.data)
})
wx.stopPullDownRefresh()
})
如果實現(xiàn)觸底下拉,請求更多15條的歌單信息?
微信自帶onReachBottom屬性,監(jiān)聽頁面觸底,我們把剛才請求歌單的方法進行一下優(yōu)化,并封裝在_getPlaylist方法中,當觸底時自動觸發(fā),并將請求的新數(shù)據(jù)拼接給playlist鼻變量。
_getPlaylist() {
wx.showLoading({
title: '加載中',
})
wx.cloud.callFunction({
name: 'music',
data: {
start: this.data.playlist.length,
count: MAX_LIMIT,
$url:'playlist'
}
}).then((res) => {
this.setData({
playlist: this.data.playlist.concat(res.result.data)
})
wx.stopPullDownRefresh()
wx.hideLoading()
})
}
調用云函數(shù)的data參數(shù)中的$url:'playlist'代表要調用的對應云函數(shù)中對應的router
當用戶下拉整個頁面的時候,怎么實現(xiàn)頁面刷新,并重置當前已加載的歌單信息數(shù)據(jù)?
在當前頁面的json文件中增加屬性"enablePullDownRefresh":true,這代表允許當前頁面下拉刷新,同時在頁面的js文件中有一個onPullDownRefresh屬性,是監(jiān)聽用戶下拉動作的
onPullDownRefresh: function() {
this.setData({
playlist:[]
})
this._getPlaylist()
},
微信暫時無法知道用戶的下拉動作是什么時候結束的,所以可以在請求數(shù)據(jù)結束的時候增加wx.stopPullDownRefresh()用來停止下拉刷新的動畫。
13.tcb-router
一個用戶在一個云環(huán)境中只能創(chuàng)建50個云函數(shù)
相似的請求歸類到同一個云函數(shù)處理
tcb-router是一個koa風格的小程序云開發(fā)云函數(shù)輕量級類路由庫,主要用于優(yōu)化服務端函數(shù)處理邏輯。
在對應的云函數(shù)中進行安裝
npm install --save tcb-router
在對應的云函數(shù)的js文件中引用
const TcbRouter = require('tcb-router')
在云函數(shù)的js文件中的入口函數(shù)中進行使用,app可以創(chuàng)建當前TcbRouter服務,這樣TcbRouter就會自動的處理event參數(shù)和路由轉發(fā),在結束的時候別忘了通過app.serve()把當前的服務返回。
···
exports.main = async(event, context) => {
const app = new TcbRouter({
event
})
return app.serve()
}
···
用ctx.body把數(shù)據(jù)返回給小程序端
app.router('playlist', async(ctx, next) => {
ctx.body = await cloud.database().collection('playlist')
.skip(event.start)
.limit(event.count)
.orderBy('creatTime', 'desc')
.get()
.then((res) => {
return res
})
})
小程序端在調用云函數(shù)時,還要在data中增加一個屬性
`$url:'xxx``
xxx對應的是name對應云函數(shù)中詳細的路由。
頁面之間的跳轉
wx.navigateTo({
url:`../../pages/musiclist/musiclist?playlistid=${this.properties.playlist.id}`,
})
上面的properties寫成data貌似也不會有什么問題。
這里問號后面的動態(tài)路由是要告訴musiclist頁面我要進入的是哪一個歌單,
musiclist頁面的onload生命周期函數(shù)中的options就可以獲取到這個傳遞過來的數(shù)據(jù),然后依據(jù)這個id去調用云函數(shù),獲取對應歌單的歌曲列表。
onLoad: function(options) {
console.log(options)
wx.showLoading({
title: '加載中',
})
wx.cloud.callFunction({
name: 'music',
data: {
playlistid: options.playlistid,
$url: 'musiclist'
}
}).then((res) => {
console.log(res)
const pl = res.result.playlist
this.setData({
musiclist: pl.tracks,
listInfo: {
coverImgUrl: pl.coverImgUrl,
name: pl.name,
}
})
this._setMuscilist()
wx.hideLoading()
})
},
當小程序開發(fā)的頁面層級比較多的時候,每次保存都會讓小程序從主頁開始,這樣很不方便,可以在上方的編譯模式中新建一個編譯模式,啟動頁面定位為想要的頁面,另外比如有啟動參數(shù),則需要填寫上,如playlistId = 28171112148
實現(xiàn)循環(huán)的歌曲列表,當前點擊的歌曲動態(tài)添加playing高亮樣式。
在小程序中,所有自定義的屬性都用data-開頭
<block wx:for="{{musiclist}}" wx:key="id">
<view class="musiclist-container {{item.id===playingId?'playing':''}}" bind:tap="onSelect" data-musicid="{{item.id}}" data-index="{{index}}">
</view>
</block>
實現(xiàn)原理:如果當前點擊事件觸發(fā)的歌曲id,和自定義屬性musicid是相等的,則可以判定當前歌曲為用戶點擊的。
點擊觸發(fā)的onSelect事件,當前點擊事件的event參數(shù)有兩個屬性,一個是target,另一個是currentTarget,而綁定的自定義屬性是在currentTarget上面。原因如下:
關于事件的幾個要素:
- 事件源,觸發(fā)事件的真正的元素
- 事件處理函數(shù)
- 事件對象,事件處理函數(shù)的默認參數(shù)event,event中有target屬性和currentTarget屬性,target對應的是事件源,currentTarget指的是綁定事件的元素
- 事件類型
onSelect(event) {
const musicid = event.currentTarget.dataset.musicid
this.setData({
playingId: musicid
})
wx.navigateTo({
url: `../../pages/player/player?musicid=${musicid}&index=${event.currentTarget.dataset.index}`,
})
}
小程序的自帶組件就是一些標簽,我們通過給標簽配置不同的屬性,就可以實現(xiàn)不同的效果
組件中的properties和data都是用來定義組件數(shù)據(jù)的,它們的差別:
properties:調用方傳給給組件的
data:組件內部使用的數(shù)據(jù)
14.本地數(shù)據(jù)存儲
將數(shù)據(jù)保存到storage中
wx.setStorage({
key: 'musiclist',
data: this.data.musiclist,
})
對于不需要進行頁面操作和顯示的數(shù)據(jù),我們可以不定義在data中,直接定義一個全局變量就行,這樣的話進行賦值也會更加的方便。
let musiclist = []
運用同步方法去給這個變量賦值,因為獲取到值需要直接進行下一步的邏輯處理
musiclist = wx.getStorageSync('musiclist')
動態(tài)的設置頁面上方的導航標題
wx.setNavigationBarTitle({
title: music.name,
})
給容器動態(tài)綁定一個鋪滿全部的背景圖片
<view class="player-container" style="background:url({{picUrl}}) center/cover no-repeat"></view>
在項目中使用iconfont
進入官網(wǎng)iconfont.cn,將想要的圖標點擊購物車圖標=>加入購物車
新建項目=>加入項目,比如:demo,點擊fontclass =>點擊查看在線鏈接,生成代碼,會生成一個css文件的鏈接地址,可以下載到本地,然后將css文件修改成wxss文件(也可以不下載,直接拷貝鏈接中的代碼放入項目中)
此時圖標wxss文件是放在項目的根目錄下的,我們要在app.wxss文件中進行引用,然后在項目中就可以通過class進行使用。
@import "iconfont.wxss";
15.音樂播放的控制
小程序提供了一個wx.getBackgroundAudioManager()方法用來控制唯一背景音樂的播放,在要播放背景音樂的頁面的js文件首先定義一個變量,去獲取全局唯一的背景音頻管理器
const backgroundAudioManager = wx.getBackgroundAudioManager()
然后通過給backgroundAudioManager 的src屬性賦值,就可以實現(xiàn)背景音樂的額播放,同時注意,還需要同時設置title,否則會報錯
backgroundAudioManager.src = JSON.parse(res.result).data[0].url
backgroundAudioManager.title = music.name
如果需要在任何界面都可以聽到這個背景音樂,則需要在app.json中配置(和pages同級)
"requireBackgroundModes":[
"audio"
],
同時還可以通過為頁面下方的mini播放器設置圖片、歌手和專輯名稱
backgroundAudioManager.coverImgUrl = music.al.picUrl
backgroundAudioManager.singer = music.ar[0].name
backgroundAudioManager.epname = music.al.name
背景音樂的暫停
backgroundAudioManager.pause()
背景音樂的播放
backgroundAudioManager.play()
在css中,animation-play-state: paused;可以讓動畫停在當前那一幀,只需要動態(tài)的給做動畫的元素添加上這個屬性,就可以實現(xiàn)動畫播放的開始與暫停
backgroundAudioManager.duration=>獲取當前背景音樂的時長,但是有時候獲取到的是underfined,解決辦法:
if(backgroundAudioManager.duration == undefined)
//上面這樣樣判定是不合理的,因為null==undefined也會是true
if(typepf backgroundAudioManager.duration != 'undefined')
//應該像上面那樣判定
怎么動態(tài)的給data中的對象中某一個屬性賦值
this.setData({
['object.xxx']:'yyyyyy'
})
this.data.progress這樣給data中的數(shù)據(jù)賦值可以成功,但不會自動響應到頁面上
backgroundAudioManager有一些事件,我們需要在這些事件上綁定對應的回調函數(shù),如:
背景音樂可以播放的時候:backgroundAudioManager.onPlay
backgroundAudioManager.seek()=》重新定義當前背景音樂的正在播放的時間點,參數(shù)為要跳轉的秒
子組件激活父元素的事件
this.triggerEvent('musicEnd')
父組件在調用子組件的標簽中進行接收,同時接收到響應后去觸發(fā)自身的onNext事件
<x-progress-bar bind:musicEnd="onNext"></x-progress-bar>
進度條的拖拽事件和backgroundAudioManager.onTimeUpdate事件是不能同時進行的,否則會造成拖拽的時候進度條會一直閃的畫面,這里的解決辦法是設置一個鎖:isMoving
當拖拽開始的時候isMoving = true
拖拽結束的時候isMoving = false
當isMoving = false的時候,onTimeUpdate里面的代碼才去執(zhí)行。
小程序控制組件的顯示與隱藏
hidden="{{flag}}" //flag為true時隱藏,為false顯示
接收父組件傳遞過來的數(shù)據(jù),如果接收的數(shù)據(jù),這個數(shù)據(jù)除了類型,還有其他的屬性,則需要寫成對象的形式,如果只需要聲明一個類型,則可以不用對象的形式
properties: {
isLyricShow: {
type: Boolean,
value: false
},
lyric: String
},
16.如何實現(xiàn)組件間傳值
自組件給父組件傳值:
自組件:
this.triggerEvent('timeUpdata',{
currentTime
})
調用這個子組件的父組件的頁面上對應的標簽
<x-process-bar bind:musicEnd="onNext" bind:timeUpdate="timeUpdata"></x-process-bar>
父組件通過觸發(fā)自定義事件接受到這個數(shù)據(jù)currentTime的同時想傳遞給另一個子組件,
通過定義事件處理函數(shù),通過給另一個需要接收數(shù)據(jù)的子組件標簽上起名一個class
timeUpdata(event){
this.selectComponent('.lyric').update(event.detail.currentTime)
},
這樣的話,另一個子組件就可以通過自身的update事件,成功接收到currentTime這個數(shù)據(jù)了。
注意:這時候子組件的update事件相當于被父組件給調用了一次。
歌詞的滾動是利用了<scroll-view>組件,scroll-top屬性可以規(guī)定這個容器里的內容向上滾動的距離,scroll-y屬性表示上下方向的滾動,scroll-with-animatio="true"表示開啟滾動過渡動畫。
scroll-top的屬性值只能是px,而我們設置的歌詞單行高度是64rpx,不同手機這個rpx代表的實際尺寸都不同,所有這里需要進行一個換算
lifetimes: {
ready() {
wx.getSystemInfo({
success: function(res) {
lyricHeight = res.screenWidth / 750 * 64
},
})
}
},
小程序寬度是750rpx,把屏幕的寬度除以750,得到的就是1rpx
17.給小程序設置全局屬性和方法
app.js中的
this.globalData = {
playingMusicId:-1
}
},
setPlayMusicId(musicId){
this.globalData.playingMusicId = musicId
},
getPlayMusicId(){
return this.globalData.playingMusicId
}
在頁面獲取全局的屬性或者方法
const app =getApp()
//在播放的音樂的方法中設置屬性
app.setPlayMusicId(musicid)
在對應的組件的頁面生命周期中,當頁面展示的時候,去觸發(fā)方法獲取到全局變量
pageLifetimes: {
show() {
this.setData({
playingId: parseInt(app.getPlayMusicId())
})
}
},
小程序下方自帶的mini控制面板的暫停和播放對應的也就是背景音樂監(jiān)聽事件中的onPause和onPlay
backgroundAudioManager.onPlay和backgroundAudioManager.onPause