小程序模板網(wǎng)

大眾點(diǎn)評(píng)點(diǎn)餐小程序開(kāi)發(fā)經(jīng)驗(yàn) - 源碼解析

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

作者介紹:周中堅(jiān),美團(tuán)點(diǎn)評(píng)工程師,4年 Web 前端開(kāi)發(fā)經(jīng)驗(yàn),主要負(fù)責(zé)過(guò)會(huì)員卡、外賣(mài)、預(yù)訂、商家平臺(tái)等業(yè)務(wù)的前端開(kāi)發(fā),現(xiàn)在是美團(tuán)點(diǎn)評(píng)點(diǎn)餐團(tuán)隊(duì)的一員。我們團(tuán)隊(duì)的小程序開(kāi)發(fā)經(jīng)驗(yàn)系列文章已經(jīng)發(fā)布了4篇,這些文章主 ...

 
 
 

作者介紹:周中堅(jiān),美團(tuán)點(diǎn)評(píng)工程師,4年 Web 前端開(kāi)發(fā)經(jīng)驗(yàn),主要負(fù)責(zé)過(guò)會(huì)員卡、外賣(mài)、預(yù)訂、商家平臺(tái)等業(yè)務(wù)的前端開(kāi)發(fā),現(xiàn)在是美團(tuán)點(diǎn)評(píng)點(diǎn)餐團(tuán)隊(duì)的一員。

我們團(tuán)隊(duì)的小程序開(kāi)發(fā)經(jīng)驗(yàn)系列文章已經(jīng)發(fā)布了4篇,這些文章主要介紹了小程序開(kāi)發(fā)概述,小程序的視圖層,小程序的邏輯層, 小程序開(kāi)發(fā)中碰到的坑(幾個(gè)設(shè)計(jì)實(shí)例)。相信大家看了這些文章,再結(jié)合官方文檔已經(jīng)可以毫無(wú)壓力地開(kāi)發(fā)小程序了,但是為什么有這些坑,是不是可以繞過(guò)去,怎么排查問(wèn)題,我們還想從源頭——小程序的源碼的角度來(lái)嘗試分析,因此有了這篇源碼解析。

代碼結(jié)構(gòu)

以 mac 電腦為例,首先進(jìn)入應(yīng)用程序文件夾,再右鍵微信開(kāi)發(fā)者工具顯示包內(nèi)容,最后讓我們進(jìn)入 ./Contents/Resources/app.nw 目錄下就可以查看小程序的源碼了,代碼結(jié)構(gòu)如圖:

 

文件夾看起來(lái)很多,但命名還算清晰,現(xiàn)在讓我們先從開(kāi)發(fā)者工具界面的角度來(lái)看下都用到了哪些文件吧。

開(kāi)發(fā)者工具

首頁(yè)

 


首頁(yè)的很多信息可以和這個(gè)項(xiàng)目中的package.json對(duì)應(yīng)起來(lái),比如name, icon, version等。

 

代理

 


代理的設(shè)置在./app/dist/components/setting/setting.js,而用戶(hù)設(shè)置的保存(包括后面要說(shuō)的模擬器設(shè)備、網(wǎng)絡(luò)等信息)是調(diào)用了./app/dist/stores/*.js方法。

 

菜單

 


上圖可以看到我對(duì)菜單做的一些定制。
菜單的設(shè)置在./app/dist/common/menu/menu.js,動(dòng)作在./app/dist/common/actions/actions.js,大家可以自行到代碼中查看文件的require進(jìn)一步分析。

 

設(shè)備及網(wǎng)絡(luò)

 


上圖可以看到我自己添加了一個(gè)設(shè)備以及一個(gè)網(wǎng)絡(luò)類(lèi)型。
模擬器的設(shè)備配置在./app/dist/config/DeviceModules.js,網(wǎng)絡(luò)配置在./app/dist/common/jssdk/osInfoSdk.js。

 

調(diào)試工具


調(diào)試工具是這一節(jié)最核心的內(nèi)容了,乍一看微信的調(diào)試工具和 chrome 的 DevTools 長(zhǎng)的很像,查看源代碼發(fā)現(xiàn)果然就是借助 chrome 的 DevTools 實(shí)現(xiàn)的。

 

 

 

其中 Console, Sources, Network 就是直接使用的 DevTools, 而 Storage, AppData, Wxml, Sensor 是自己實(shí)現(xiàn)的。

參照 Storage, AppData, Wxml, Sensor 這些調(diào)試工具,這些我們要自己添加一個(gè)其實(shí)非常簡(jiǎn)單,只要在./app/dist/extensions目錄下新建一個(gè)文件夾,用html/css/js完成這個(gè)工具的功能,再改devtools.html將這個(gè)工具引入進(jìn)來(lái)chrome.devtools.panels.create()即可,如圖:

 

有趣的是,在0.15.150201這個(gè)測(cè)試版中已經(jīng)發(fā)現(xiàn)了一個(gè)名為Bluetooth的開(kāi)發(fā)工具。

weapp

上面一節(jié)主要講的是小程序開(kāi)發(fā)者工具的源碼,我們借助分析源碼可以搞清楚代理是怎么設(shè)置的,模擬器的設(shè)備和網(wǎng)絡(luò)如何添加,怎樣開(kāi)發(fā)一個(gè)滿(mǎn)足自己特定需求的 DevTool。

這一節(jié)主要介紹我們寫(xiě)的微信小程序的代碼是如何變成頁(yè)面在用戶(hù)的終端運(yùn)行的:

  • tpl 文件夾下是頁(yè)面模板。
  • onlinevendor/wcc 在編譯時(shí)把 wxml 文件 轉(zhuǎn)為 js,onlinevendor/wcsc 在編譯時(shí)把 wxss 文件轉(zhuǎn)化為 js,這也是編譯包比代碼庫(kù)要大不少的重要原因。
  • trans 文件夾下有五個(gè)方法,其中 transConfigToPf 將配置轉(zhuǎn)成pageFrame,trans/transWxmlToHtml 將 wxml 轉(zhuǎn)成 dom tree, 再進(jìn)一步用 webview 渲染,trans/transWxssToCss 將 wxss 轉(zhuǎn)成 css,提供 view 層樣式。
  • onlinevendor/WAService.js 提供了service 層幾乎一切功能。

pageFrame

首先是看一下剛才提到的 pageFrame,對(duì)應(yīng)的 transConfigToPf 主要用字符串替換的方式完成轉(zhuǎn)換。

<!DOCTYPE html>
<html lang="zh-CN">

<head>
  <link href="https://res.wx.qq.com/mpres/htmledition/images/favicon218877.ico" rel="Shortcut Icon">
  <meta http-equiv="Content-Security-Policy" content="script-src 'self' *.qq.com 'unsafe-inline' 'unsafe-eval'">
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0" />

  <script>
    var __webviewId__;
  </script>

  <!-- percodes -->

  <!--{{appconfig}}-->

  <!--{{pageconfig}}-->

  <!--{{WAWebview}}-->

  <!--{{reportSDK}}-->

  <!--{{webviewSDK}}-->

  <!--{{exparser}}-->

  <!--{{components_js}}-->

  <!--{{virtual_dom}}-->

  <!--{{components_css}}-->

  <!--{{allWXML}}-->

  <!--{{eruda}}-->

  <!--{{style}}-->

  <!--{{currentstyle}}-->

  <!--{{generateFunc}}-->

</head>

<body>
  <div></div>
</body>

</html>

appservice 頁(yè)面模板

開(kāi)發(fā)者工具提供了封裝過(guò)的 wxml pannel, 我們并不能從中看到頁(yè)面完整的 dom 結(jié)構(gòu),但是用$('*')選擇器我們可以看到頁(yè)面的 appservice 模板,看這段代碼我們可以分析出小程序是如何使用 wxml, wxss, js 將頁(yè)面生成出來(lái)的。

<!DOCTYPE html>
<html>

<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  <meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline' 'unsafe-eval'">
  <link href="https://res.wx.qq.com/mpres/htmledition/images/favicon218877.ico" rel="Shortcut Icon">
  <script>
  var __wxAppData = {}
  var __wxRoute
  var __wxRouteBegin
  global = {}
  </script>
  <script></script><!-- 加載一堆script標(biāo)簽 -->
</head>

<body>
  <p>
    開(kāi)發(fā)者工具使用 nwjs 來(lái)模擬小程序的實(shí)現(xiàn),幫助大家來(lái)開(kāi)發(fā)和調(diào)試微信小程序,所以這里是一個(gè) webview,但真實(shí)
    的手機(jī)端是運(yùn)行在 jscore 中的,所以請(qǐng)不要使用任何 bom 對(duì)象。
  </p>
  <p>
    我們建議你先完整閱讀該開(kāi)發(fā)文檔,這將有助于更快地完成開(kāi)發(fā)。如果發(fā)現(xiàn)我們的文檔有任何錯(cuò)漏,
    或者開(kāi)發(fā)過(guò)程中有任何疑問(wèn)或者你有更好的建議,歡迎通過(guò)下列郵箱聯(lián)系我們

    weixin_developer@qq.com

    或者訪問(wèn)微信小程序開(kāi)發(fā)者社區(qū)提交問(wèn)題:

    https://developers.weixin.qq.com
  </p>
  <script>
    window._____sendMsgToNW({
      sdkName: 'APP_SERVICE_COMPLETE'
    })
  </script>
</body>

</html>

WAService.js

WAService.js 是小程序頁(yè)面運(yùn)行的核心方法,主要有幾大功能:

  • 內(nèi)置的 report 方法定義
  • 微信小程序 API 封裝
  • WeixinJSBridge 封裝
  • appServiceEngine 模塊
    // 內(nèi)置的 report 方法定義,用于內(nèi)部 API 的調(diào)用日志 & 報(bào)錯(cuò)記錄等。
    var Reporter = {
      surroundThirdByTryCatch,
      slowReport,
      speedReport,
      reportKeyValue,
      reportIDKey,
      thirdErrorReport,
      errorReport,
      log,
      submit,
      registerErrorListener,
      unRegisterErrorListener,
      triggerErrorMessage
    }
    // 微信小程序 API 封裝,所有文檔中的 [API](https://mp.weixin.qq.com/debug/wxadoc/dev/api/)都在這里封裝了,以showModal為例簡(jiǎn)單分析一下
    showModal: function() {
      var e = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : {}
        , t = {
          title: "",
          content: "",
          confirmText: "確定",
          cancelText: "取消",
          showCancel: !0,
          confirmColor: "#3CC51F",
          cancelColor: "#000000"
      };// 默認(rèn)值,此處比文檔準(zhǔn)確
      if (t = (0,
      f.extend)(t, e),
      a("showModal", t, {// 調(diào)用 jsbridge,見(jiàn)下方代碼
          title: "",
          content: "",
          confirmText: "",
          cancelText: "",
          confirmColor: "",
          cancelColor: ""
      }))
          return t.confirmText.length > 4 ? void B("showModal", e, "showModal:fail confirmText length should not large then 4") : t.cancelText.length > 4 ? void B("showModal", e, "showModal:fail cancelText length should not large then 4") : void (0, // 各種校驗(yàn)
          u.invokeMethod)("showModal", t, {
              beforeSuccess: function(e) {
                  e.confirm = Boolean(e.confirm)// 返回值處理
              }
          })
    }
    // 此處調(diào)用 WeixinJSBridge,此外還對(duì)每個(gè) API 調(diào)用記 log,方便微信小程序的問(wèn)題排查
    function a() {
      var e = Array.prototype.slice.call(arguments)
        , t = e[1];
      e[1] = function(e, n) {
          var o = e.data
            , r = e.options
            , i = arguments.length > 2 && void 0 !== arguments[2] ? arguments[2] : {}
            , a = r && r.timestamp || 0
            , s = Date.now();
          "function" == typeof t && t(o, n),
          Reporter.speedReport({
              key: "webview2AppService",
              data: o || {},
              timeMark: {
                  startTime: a,
                  endTime: s,
                  nativeTime: i.nativeTime || 0
              }
          })
      }
      ,
      WeixinJSBridge.subscribe.apply(WeixinJSBridge, e)
    }
    // WeixinJSBridge 封裝,底層是調(diào)用 WeixinJSCore
    e.WeixinJSBridge = {
      invoke: d,
      invokeCallbackHandler: p,
      on: h,
      publish: v,
      subscribe: g,
      subscribeHandler: y
    }
    // 內(nèi)置的 jsbridge core
    WeixinJSCore = {
      invokeHandler,
      publishHandler
    }
    // setData 方法定義,邏輯層通過(guò) setData 方法改變 virtual dom,改變 dom tree,從而改變視圖層
    // appServiceEngine 模塊,提供 App 和 Page 相關(guān)的接口

總結(jié)

如果是為了源碼分析而進(jìn)行源碼分析,我覺(jué)得大可不必,在小程序的場(chǎng)景下,源碼分析的價(jià)值在于:

  • 官方文檔不一定和實(shí)際情況是對(duì)齊的,開(kāi)發(fā)時(shí)碰到不一致的情況可以查閱源碼,以此為準(zhǔn)。
  • 熟悉源碼結(jié)構(gòu)可以快速定位問(wèn)題,提升開(kāi)發(fā)效率,甚至給自己開(kāi)發(fā)合適的 DevTool。
  • 小程序可以認(rèn)為是前端的一個(gè)子集,而且相對(duì)封閉,開(kāi)發(fā)時(shí)會(huì)有各種約束,查閱源碼可以有助于小程序的設(shè)計(jì)。


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