小程序模板網(wǎng)

WeScale 技術(shù)篇 —— mpvue 與微信小程序的火花

發(fā)布時(shí)間:2018-05-09 12:06 所屬欄目:小程序開發(fā)教程

介紹

項(xiàng)目介紹

WeScale 定位為音樂訓(xùn)練小程序,初期規(guī)劃了基礎(chǔ)音階的三個(gè)訓(xùn)練,以及他們的鏡像模式。

  • 數(shù)字簡譜
  • 字母簡譜
  • 數(shù)字簡譜對字母簡譜

后期看情況更新追加其他訓(xùn)練。

產(chǎn)品展示

掃描下方小程序碼或在微信小程序中搜索 WeScale,即可使用。

人員介紹

緣起

明神每晚都要練著他的電吉他,敲著他的木魚,突然一道光在腦海中閃過,機(jī)智的他迅速捕獲到,當(dāng)晚凌晨三點(diǎn)做完了這次小程序的原型。

之前和老陳搞了個(gè) A股股票助手 — stock-helper ,這次有明神帶路,我們都想積累點(diǎn)小程序開發(fā)的經(jīng)驗(yàn),于是我和老陳就上車了。(滴~~學(xué)生卡)

恰逢美團(tuán)剛剛開源了 mpvue ,短短幾周就迅速獲得幾千個(gè) star,在 mpvue 開源前,最流行的應(yīng)該是 wepy 。據(jù)說用 mpvue,能夠像德芙一樣順滑地使用 vue 寫微信小程序,于是我們開始了踩坑之路。

項(xiàng)目統(tǒng)計(jì)

預(yù)計(jì)一周完成,畢竟是大家都有正經(jīng)事要做,硬是拖到了兩周才完成。四個(gè)分支,總計(jì)提交 51次,越到 deadline 提交越多,目前已發(fā)布 v1.0.0 版本,已審核上線。

踩到的坑

  • 微信小程序不能使用本地資源

這個(gè)坑很常見,微信小程序不支持本地引用圖片、音頻、視頻,所以需要外鏈。對于圖片還可以使用 Base64 編碼,直接在 html 或 css 中引用。根據(jù)圖片根據(jù)圖片體積或者可維護(hù)性考慮,酌情使用外鏈或者Base64編碼。

  • 新增頁面需要 npm run dev

這個(gè)是 mpvue 的問題。常見問題可以發(fā)現(xiàn)。解決的方法就是手動 npm run dev 一下。

  • 生命周期問題

mpvue 是兼容微信小程序的生命周期與 vue 的生命周期,也就是 vue 實(shí)例會接管小程序 Page 實(shí)例的生命鉤子,因此需要使用到小程序的生命周期鉤子時(shí),可將相應(yīng)的鉤子方法定義在 vue 實(shí)例中,如定義當(dāng)前Page的分享標(biāo)題內(nèi)容圖片:


new Vue({
  data () {
    return {
      score: ''
    }
  },
  onShareAppMessage (res) {
    return {
      title: '我獲得 ' + this.score + ' 分,快來一起掌握基礎(chǔ)音階知識吧!',
      path: '/pages/index/index',
      imageUrl: 'https://wechat.dddog.com.cn/static/wescale.jpg'
    }
  }
})

這個(gè)不知道如何描述,大致是非當(dāng)前頁面的 create() 會在當(dāng)前頁面執(zhí)行,解決方法,用小程序的 onload()/ vue 的 mounted(),遇到問題看圖就好:

  • Class 與 Style 綁定

不支持 vue 官方文檔:Class 與 Style 綁定 中的 classObject 和 styleObject 語法。 暫不支持在組件上使用 Class 與 Style 綁定

不支持就不用咯~

  • 沒有 BOM/DOM 操作

mpvue 使得開發(fā)者可以使用標(biāo)準(zhǔn) html、css 去編寫小程序,當(dāng)我們查看 mpvue 項(xiàng)目中的 dist 文件夾時(shí)可以發(fā)現(xiàn),編寫的 html、css 被解析成了小程序的 wxml、wxss ,固然小程序的運(yùn)行環(huán)境也就是非標(biāo)準(zhǔn)的 WebView 了。因此我們web開發(fā)進(jìn)行經(jīng)常使用的 browser、navigator 實(shí)例自然是無法使用了,取而代之的是使用小程序?yàn)g覽器提供的API —— wx實(shí)例去操作native元素。至于 DOM 操作,即使在vue中也是不建議使用的,還是用數(shù)據(jù)驅(qū)動去轉(zhuǎn)化吧。也就是說所有關(guān)于 BOM / DOM 的操作都不行。用 vue 第三方 UI庫時(shí)要注意, Dom 和 Bom 相關(guān)的 API 操作都無法實(shí)現(xiàn)。 解決方案: 這塊主要是動畫不能用,那就用 css3 咯~

  • 組件名不要和微信的組件名重名

試著寫一個(gè) swicth 的組件,發(fā)現(xiàn)渲染結(jié)果不對,查了原因才發(fā)現(xiàn),微信小程序也有個(gè) switch 的組件。 解決方案: 改名字啊。命名規(guī)范!

  • 微信小程序多聲道

按正常的套路去使用小程序的 api —— wx.createInnerAudioContext() 是無法創(chuàng)建多聲道的。本次技術(shù)的難點(diǎn)也在于如何創(chuàng)建微信小程序的多聲道。查了一圈的資料,關(guān)于這點(diǎn)的資料甚少。查到一篇博客,通過創(chuàng)建多個(gè) innerAudioContext 實(shí)例化對象,輪流調(diào)用的方式。對于原作者說小程序只能同時(shí)存在5個(gè)音頻實(shí)例這一定,不敢茍同。畢竟我直接創(chuàng)建了 30個(gè)都沒問題,哈哈


const audioContextNum = 30
let globalAudioContext = Array.from({ length: audioContextNum },
  (v, k) => wx.createInnerAudioContext())

如何尋找當(dāng)前可用的聲道,也是個(gè)難點(diǎn),大致的思想是,把正在播放的實(shí)例封鎖,待實(shí)例的 onEnded() 回調(diào)執(zhí)行時(shí)取消封鎖,使用時(shí)需要遍歷所有實(shí)例,尋找當(dāng)前可用的實(shí)例,看實(shí)例代碼(與實(shí)際代碼有刪改):


// 自動尋找一個(gè)當(dāng)前可用的 audioContext 實(shí)例
export function playedMusic (url) {
  let contextList = store.getters.globalAudioContext

  while (contextList !== store.getters.audioContextStatus.map(item => item === false).length) {
    let audioContextStatus = store.getters.audioContextStatus
    let index = store.getters.currentAudioIndex
    // 如果當(dāng)前可用,封鎖
    if (audioContextStatus[index]) {
      store.commit('setAudioContextStatus', {index, status: false})
      break
    } else {
      // 否則 ++index
      store.commit('setCurrentAudioIndex', ++index)
    }
  }

  const resultPromise = new Promise((resolve, reject) => {
    contextList[index].onPlay(() => {})
    contextList[index].onError((res) => {
      reject(res)
    })
    contextList[index].onEnded((res) => {
      reset(resolve)
    })
  })

  return resultPromise
}
  • 微信小程序的緩存

實(shí)際開發(fā)過程中發(fā)現(xiàn)。如果不預(yù)先對音頻進(jìn)行緩存,實(shí)際播放時(shí)會有一定的延遲,視網(wǎng)絡(luò)情況。解決方案是先預(yù)加載,然后存在小程序的緩存中,官網(wǎng)介紹緩存有 10 M,足夠用了。 首先是下載文件 wx.downloadFile(),得到 tempFilePath,再把臨時(shí)文件保存為本地文件 wx.saveFile(),得到 savedFilePath,再將本地文件的的路徑保存在緩存中 wx.setStorage()。這么多異步操作,當(dāng)然用 Promise 再封裝一下啦。

多文件的下載、保存、緩存, 回調(diào)、遞歸的思想:


// 加載資源, 加載完隱藏loading
  _load(0, () => {
    // 更改Audio.js的config對象屬性。
    config.musicUrl = JSON.parse(musicUrlTemp)

    const temp = JSON.parse(musicUrlTemp)
    temp.tempVerison = tempVerison
    wx.setStorage({key: 'musicUrl', data: temp})
    wx.hideLoading()
  })
  function _load (index, callback) {
    if (!musicUrlArr[index]) {
      callback()
    } else {
      downloadFile(musicUrlArr[index]).then((tempFilePath) => {
        saveFile(tempFilePath).then((savedFilePath) => {
          musicUrlTemp = musicUrlTemp.replace(
            musicUrlArr[index],
            savedFilePath
          )
          index++
          _load(index, callback)
        })
      })
    }
  }

緩存是否存在及緩存版本的判斷:


// 判斷是否已有緩存且緩存版本正確
  if (temp && temp.tempVerison === tempVerison) {
    return false
  }
  • 全局變量

遇到很多需要全局變量,特別是狀態(tài)的,最好統(tǒng)一管理。vue 的vuex 是專為 Vue.js 應(yīng)用程序開發(fā)的狀態(tài)管理模式。使用過程遇到的坑是無法使用它的輔助函數(shù) mapState、 mapGetters、 mapActions、 mapMutations 等。看下 mpvue 的 issue 感覺是 mpvue 的問題。 解決方案: 用最原始的 store.commit()、 store.getter

  • 數(shù)據(jù)分析及合法域名

調(diào)用微信小程序的網(wǎng)絡(luò)請求 wx.request()、 wx.downloadFile() 之類 都需要 https 協(xié)議。 調(diào)微信的數(shù)據(jù)分析還要隔兩個(gè)小時(shí)獲取 access_token, 這些就是要服務(wù)器端的配置了。

條件: 域名及域名證書、服務(wù)器

獲取 token 及 服務(wù)器寫接口返回靜態(tài)文件及微信的數(shù)據(jù)分析接口 可以參考這個(gè), node.js 寫的,寫的很隨意,隨便看看。

  • ES6 的模塊動態(tài)引用

參考 博客 :

  1. ES6 模塊中的值屬于【動態(tài)只讀引用】。只說明一下復(fù)雜數(shù)據(jù)類型。
  2. 對于只讀來說,即不允許修改引入變量的值, import 的變量是只讀的,不論是基本數(shù)據(jù)類型還是復(fù)雜數(shù)據(jù)類型。當(dāng)模塊遇到 import 命令時(shí),就會生成一個(gè)只讀引用。等到腳本真正執(zhí)行時(shí),再根據(jù)這個(gè)只讀引用,到被加載的那個(gè)模塊里面去取值。
  3. 對于動態(tài)來說,原始值發(fā)生變化, import 加載的值也會發(fā)生變化。不論是基本數(shù)據(jù)類型還是復(fù)雜數(shù)據(jù)類型。

// b.js
export let counter = {
  count: 1
}
setTimeout(() => {
  console.log('b.js-1', counter.count)
}, 1000)

// a.js
import { counter } from './b.js'
counter = {}
console.log('a.js-1', counter)

// Syntax Error: "counter" is read-only

雖然不能將 counter 重新賦值一個(gè)新的對象,但是可以給對象添加屬性和方法。此時(shí)不會報(bào)錯(cuò)。這種行為類型與關(guān)鍵字 const 的用法。


// a.js
import { counter } from './b.js'
counter.count++
console.log(counter)

// 2

致謝

致謝所有參與產(chǎn)品、開發(fā)、測試,貢獻(xiàn)出創(chuàng)意想法與建議的小伙伴。

 


易優(yōu)小程序(企業(yè)版)+靈活api+前后代碼開源 碼云倉庫:starfork
本文地址:http://www.u-renovate.com/wxmini/doc/course/24362.html 復(fù)制鏈接 如需定制請聯(lián)系易優(yōu)客服咨詢:800182392 點(diǎn)擊咨詢
QQ在線咨詢