商城系統(tǒng) 注冊(cè)

怎么制作唱吧小程序,類似唱吧的小程序開發(fā)文檔

2018-08-20|HiShop
導(dǎo)讀:唱吧小程序開發(fā)上線還不到一個(gè)月的時(shí)間,唱吧小程序通過借助小程序的用完即走特性,使小程序用戶數(shù)突破200萬,下面就以最近接觸到的一款小程序?yàn)槔?,?jiǎn)單總結(jié)一下小程序底層框架和一些...

唱吧小程序開發(fā)上線還不到一個(gè)月的時(shí)間,唱吧小程序通過借助小程序的用完即走特性,使小程序用戶數(shù)突破200萬,下面就以最近接觸到的一款小程序?yàn)槔?,?jiǎn)單總結(jié)一下小程序底層框架和一些api接口方面的設(shè)計(jì)思路。

1小程序框架淺析

大家都說小程序體驗(yàn)好,即開即用,和普通Webview渲染的H5相比頁面啟動(dòng)速度、流暢度等方面好很多,這個(gè)問題我認(rèn)為需要從幾個(gè)方面考慮,首先,拋開產(chǎn)品業(yè)務(wù)層面的設(shè)計(jì)和優(yōu)化,就是小程序底層框架的設(shè)計(jì)和實(shí)現(xiàn)方面的特點(diǎn)。

當(dāng)我們新建或打開一個(gè)小程序項(xiàng)目(以唱吧比賽小程序?yàn)槔纯煽吹饺缦聢D的項(xiàng)目結(jié)構(gòu)。

怎么制作唱吧小程序,類似唱吧的小程序開發(fā)文檔

小程序入口文件為app.js, 全局樣式文件為app.wxss,全局配置文件為app.json, 每個(gè)頁面中再分視圖wxml,wxss和邏輯js、文件配置json等,從這里我們可以看出,整個(gè)小程序的上層框架,也就是大體分為視圖層和邏輯層兩個(gè)部分。 (摘自官方文檔https://developers.weixin.qq.com/miniprogram/dev/framework/structure.html)

怎么制作唱吧小程序,類似唱吧的小程序開發(fā)文檔

小程序采用的MINA框架,View層主要用來渲染頁面結(jié)構(gòu),App Service層用來邏輯處理、數(shù)據(jù)請(qǐng)求、接口調(diào)用,它們?cè)趦蓚€(gè)線程里運(yùn)行,整個(gè)小程序是只有一個(gè)App Service的,并且整個(gè)小程序的生命周期內(nèi)它是常駐內(nèi)存的。View層主要使用WebView渲染,而App Service邏輯層是使用JSCore運(yùn)行。

通信方面,View和AppService是雙線程通信的,主要通過系統(tǒng)層的JSBridage進(jìn)行通信,AppService把數(shù)據(jù)變化通知到View,表現(xiàn)方法也就是setData方法,觸發(fā)View頁面更新,View把觸發(fā)的事件通知到AppService進(jìn)行業(yè)務(wù)處理。

這里要說的是,小程序是沒有DOM結(jié)構(gòu)的,那么視圖層的渲染是如何做到的呢,就是運(yùn)行環(huán)境中會(huì)把pages中的WXML的節(jié)點(diǎn)樹結(jié)構(gòu),轉(zhuǎn)化為JS的對(duì)象,進(jìn)行渲染,這也是小程序體驗(yàn)優(yōu)于普通分享頁面的一大原因,省去了很多關(guān)于瀏覽器DOM的操作,由JS運(yùn)行環(huán)境之間進(jìn)行渲染解析。

2唱吧小程序底層搭建

那么話說回來,基于良好的框架,這次在搭建唱吧小程序底層的時(shí)候,我們其實(shí)做了哪些事情呢。

首先,我們并沒有進(jìn)行純Native層的搭建和改造,而是對(duì)上述提到的API層的一次的封裝,尤其是在關(guān)于網(wǎng)絡(luò)請(qǐng)求的改造和小程序啟動(dòng)的登錄流程方面,我們前端團(tuán)隊(duì)嘗試去做一些分層和優(yōu)化。

  • 網(wǎng)絡(luò)請(qǐng)求方面

首先網(wǎng)絡(luò)請(qǐng)求優(yōu)化方面,微信提供的請(qǐng)求接口基本長(zhǎng)這樣:


  1. wx.request({

  2.  url: 'test.php', //僅為示例,并非真實(shí)的接口地址

  3.  data: {

  4.     x: '' ,

  5.     y: ''

  6.  },

  7.  header: {

  8.      'content-type': 'application/json' // 默認(rèn)值

  9.  },

  10.  success: function(res) {

  11.    console.log(res.data)

  12.  }

  13. })

是不是感覺和之前的某種請(qǐng)求模式很像,沒錯(cuò),就是古老的$.ajax,這時(shí)候我們又想起了ajax的回調(diào)地獄,如果頁面的請(qǐng)求很多,請(qǐng)求的順序還有限定,瞬間又是各種嵌套,可以說是要從請(qǐng)求到懵逼了。

所以為了解決回調(diào)地獄和同時(shí)優(yōu)化請(qǐng)求代碼邏輯,我們?cè)诜庋bwx.request的同時(shí),我們?cè)谛〕绦蜷_發(fā)中,引入了async/await語法糖,用到了來自facebook的regenerator模塊(詳情請(qǐng)戳:https://github.com/facebook/regenerator),async、await函數(shù)經(jīng)babel編譯后,再用regenerator-runtime模塊用于提供功能實(shí)現(xiàn),這一方面也得力于小程序支持ES6語法的編譯。

實(shí)現(xiàn)過程中,單獨(dú)用一個(gè)公共方法封裝,返回wx.request的promise


  1. //wechat.js

  2.  

  3. const request = (url,options) => {

  4.  return new Promise((resolve, reject) => {

  5.    wx.request({

  6.      url: url,

  7.      method: options.method,

  8.      data: Object.assign({}, options.data),

  9.      header: options.header,

  10.      success: resolve,

  11.      fail: reject

  12.    })

  13.  })

  14. }

之后在我們的上層公共庫中,編寫與請(qǐng)求相關(guān)的處理邏輯。


  1. // changba.js

  2.  

  3. const regeneratorRuntime = require('./regenerator-runtime.js')

  4. const wechat = require('./wechat')

  5. const URI = 'xxx'

  6.  

  7. const requestAPI = async (url,opt) => {

  8.  const app = getApp()

  9.  let options = Object.assign({data: {}},opt)

  10.    if (/^\/api\/(.+)$/.test(url)) {

  11.        url = URI + url;

  12.    }

  13.    if (!options.method) {

  14.        options.method = 'POST';

  15.    }

  16.    let header = {

  17.        'Content-Type': 'application/x-www-form-urlencoded'

  18.    }

  19.    options.header = options.header || header ;

  20.    //除了login方法  其余接口都要加入sessionInfo也就是后端加密過的session_key

  21.    if (!url.includes('/checkCode')) {

  22.      options.data['sessionInfo'] = app.globalData.sessionkey;

  23.    }

  24.    let isTimeout = false;

  25.    try {

  26.      const ree = await wechat.checkSession();

  27.    } catch (error) {

  28.      isTimeout = true;

  29.    };

  30.    try {

  31.      if (isTimeout) {

  32.        let aaa = await login(app);

  33.      }

  34.      wx.showLoading({

  35.        title: '加載中'

  36.      });

  37.        const res = await wechat.request(url,options)

  38.        if (res && res.statusCode) {

  39.            if (res.statusCode != 200) {

  40.                if (wx.hideLoading) {

  41.                    wx.hideLoading()

  42.                }

  43.                wx.showModal({

  44.                    content: wechat.errMsg(res.statusCode).message || '請(qǐng)求失敗,請(qǐng)重新嘗試',

  45.                    title: '提示',

  46.                    showCancel: false

  47.                })

  48.            } else {

  49.                if (res.data && res.data.code === 1) {

  50.                  if (wx.hideLoading) {

  51.                     wx.hideLoading()

  52.                  }

  53.                  return res.data

  54.                } else {

  55.                    // xxx 其他情況業(yè)務(wù)邏輯處理

  56.                }

  57.            }

  58.        }

  59.    } catch (error) {

  60.        console.log('請(qǐng)求異常信息:' + error)

  61.        if (wx.hideLoading) {

  62.          wx.hideLoading()

  63.        }

  64.        wx.showModal({

  65.            content: '請(qǐng)求信息異常',

  66.            title: '',

  67.            showCancel: false

  68.        })

  69.    }

  70. }

上述封裝過程中,所以除了考慮到請(qǐng)求超時(shí)、檢查用戶身份等操作,還可以加入session過期等相關(guān)其他的業(yè)務(wù)處理邏輯,這也是自己搭建請(qǐng)求的好處,針對(duì)自己的業(yè)務(wù)需求,進(jìn)行匹配和改造。

然而在經(jīng)歷這樣兩層封裝之后,在寫業(yè)務(wù)邏輯代碼的過程中,就可以一目了然的發(fā)送請(qǐng)求了,達(dá)到邏輯清晰且書寫自如,如果習(xí)慣了fetch以及axios的朋友應(yīng)該都會(huì)比較喜歡這種方式。


  1.   async getdata() {

  2.     let self = this;

  3.     let cb_getdata = await app.changba.requestAPI('/api/xxx', { data: { id: self.data.id } });

  4.     if (cb_getdata && cb_getdata.code === 1) {

  5.           // xxx

  6.     }

  7.   }

  • 登錄流程方面

下面說下,啟動(dòng)小程序后的登錄流程方面,在這一方面,小程序與其他不同的是,沒有固定的登錄啟動(dòng)頁面,而是完全后臺(tái)交互,當(dāng)然根據(jù)產(chǎn)品定位和需求,也可以自己做一套登錄系統(tǒng)~

電話咨詢 預(yù)約演示 0元開店