欧美三级国产三级日韩三级_亚洲熟妇丰满大屁股熟妇_欧美亚洲成人一区二区三区_国产精品久久久久久模特

Taro 轉(zhuǎn)快應(yīng)用的那些事(三) - 新聞資訊 - 云南小程序開(kāi)發(fā)|云南軟件開(kāi)發(fā)|云南網(wǎng)站建設(shè)-昆明葵宇信息科技有限公司

159-8711-8523

云南網(wǎng)建設(shè)/小程序開(kāi)發(fā)/軟件開(kāi)發(fā)

知識(shí)

不管是網(wǎng)站,軟件還是小程序,都要直接或間接能為您產(chǎn)生價(jià)值,我們?cè)谧非笃湟曈X(jué)表現(xiàn)的同時(shí),更側(cè)重于功能的便捷,營(yíng)銷(xiāo)的便利,運(yùn)營(yíng)的高效,讓網(wǎng)站成為營(yíng)銷(xiāo)工具,讓軟件能切實(shí)提升企業(yè)內(nèi)部管理水平和效率。優(yōu)秀的程序?yàn)楹笃谏?jí)提供便捷的支持!

您當(dāng)前位置>首頁(yè) » 新聞資訊 » 小程序相關(guān) >

Taro 轉(zhuǎn)快應(yīng)用的那些事(三)

發(fā)表時(shí)間:2021-1-5

發(fā)布人:葵宇科技

瀏覽次數(shù):189

前言

Taro 組件的生命周期基本和 React 組件的生命周期完全相同,這也是為何 Taro 上手這么容易的原因。但它是如何將生命周期對(duì)應(yīng)的轉(zhuǎn)化到小程序,快應(yīng)用,H5 等其他端語(yǔ)言的生命周期上呢?而且它真的能夠完全覆蓋到其他端組件(或頁(yè)面)的所有生命周期嗎?

內(nèi)容大綱

  1. Taro 組件生命周期轉(zhuǎn)化的基本原理
  2. 如何在 Taro 中攔截快應(yīng)用原生的生命周期
  3. 全局的錯(cuò)誤監(jiān)控

Taro 組件生命周期轉(zhuǎn)化的基本原理

其實(shí)理解生命周期的實(shí)現(xiàn)原理,就知道這很簡(jiǎn)單。只是將 Taro 組件上暴露的方法(如 componentWillMount、componentDidMount、componentDidShow等等),在對(duì)應(yīng)的原生生命周期方法函數(shù)中去執(zhí)行就完事了。話不多說(shuō),先看 Taro 中摘錄的代碼片段。

// taro-quickapp/dist/index.js

var componentConf = {
  data: initData,
  onInit: function onInit() {
    /** 這部分刪除了  */
  },
  onReady: function onReady() {
    if (!isPage) {
      initComponent.apply(this, [ComponentClass, isPage])
    }

    var component = this.$component

    if (!component.__mounted) {
      component.__mounted = true
      componentTrigger(component, 'componentDidMount')
    }
  },
  onDestroy: function onDestroy() {
    componentTrigger(this.$component, 'componentWillUnmount')
    var component = this.$component
    component.hooks.forEach(function (hook) {
      if (isFunction(hook.cleanup)) {
        hook.cleanup()
      }
    })
    var events = component.$$renderPropsEvents

    if (isArray$1(events)) {
      events.forEach(function (e) {
        return taro.eventCenter.off(e)
      })
    }
  },
}

if (isPage) {
  componentConf['onShow'] = function () {
    componentTrigger(this.$component, 'componentDidShow')
  }

  componentConf['onHide'] = function () {
    componentTrigger(this.$component, 'componentDidHide')
  }

  pageExtraFns.forEach(function (fn) {
    if (componentInstance[fn] && typeof componentInstance[fn] === 'function') {
      componentConf[fn] = function () {
        var component = this.$component

        if (component[fn] && typeof component[fn] === 'function') {
          return component[fn].apply(component, arguments)
        }
      }
    }
  })
  globalRef.componentPath = isPage
  addLeadingSlash$1(isPage) &&
    cacheDataSet(addLeadingSlash$1(isPage), ComponentClass)
}

bindStaticFns(componentConf, ComponentClass)
bindProperties(componentConf, ComponentClass, isPage)
ComponentClass['privateTaroEvent'] &&
  bindEvents(componentConf, ComponentClass['privateTaroEvent'])
return componentConf
復(fù)制代碼

簡(jiǎn)單說(shuō)明:componentConf 可以理解為原生,也就是 componentConf['onShow'] 就表示了快應(yīng)用中頁(yè)面的生命周期 onShow。最后就變成了在快應(yīng)用 onShow 的時(shí)候執(zhí)行了 Taro componentDidShow 的方法,就這么簡(jiǎn)單。

如何在 Taro 中攔截快應(yīng)用原生的生命周期

上面已經(jīng)清晰了 Taro 轉(zhuǎn)快應(yīng)用的生命周期方式,但同時(shí)我們也發(fā)現(xiàn)了還有好些快應(yīng)用的生命周期(如 APP 的生命周期 onShow、onHide、onError等等),Taro 并沒(méi)有支持到(原因可能是還沒(méi)有跟上快應(yīng)用的迭代變化,或者認(rèn)為我們就是不需要.)。雖然有些功能社區(qū)暫時(shí)還未支持,但是偏偏我們業(yè)務(wù)場(chǎng)景上就要用了,那我們也不是只能反饋社區(qū)后等社區(qū)結(jié)果的,我們完全也是可以自己封裝辦到的。

那我們就先分析下 Taro 編譯后的快應(yīng)用代碼,代碼路徑在 dist/quickapp/src/app.ux。

// app.ux 底部

exports.default = require('./npm/@tarojs/taro-quickapp/index.js').default.createApp(_App);

_index2.default.initPxTransform({
  "designWidth": 750,
  "deviceRatio": {
    "640": 1.17,
    "750": 1,
    "828": 0.905
  }
});
script>
復(fù)制代碼

其實(shí)發(fā)現(xiàn)編譯后的源碼很好理解,exports.default 是原生快應(yīng)用語(yǔ)言要求導(dǎo)出的 JS 對(duì)象, 在這里導(dǎo)出的是 Taro createApp 方法執(zhí)行后返回的一個(gè)對(duì)象。那么假如我們對(duì)這個(gè)即將導(dǎo)出的對(duì)象做重新賦值,并添加上我們想要添加的原生生命周期方法,那么是不是就已經(jīng)達(dá)到了攔截原生生命周期的目的。

對(duì) Taro 底層做一定的修改

所有修改的代碼內(nèi)容如下:

// @tarojs/cli/src/mini/astProcess.ts

switch (type) {
    case PARSE_AST_TYPE.ENTRY:
    const pxTransformConfig = {
        designWidth: projectConfig.designWidth || 750
    }
    if (projectConfig.hasOwnProperty(DEVICE_RATIO_NAME)) {
        pxTransformConfig[DEVICE_RATIO_NAME] = projectConfig.deviceRatio
    }
    if (isQuickApp) {
        if (!taroImportDefaultName) {
        node.body.unshift(
            template(`import Taro from '${taroMiniAppFrameworkPath}'`, babylonConfig as any)()
        )
        }
        node.body.unshift(template(`var quickappLifecycle = global.quickappLifecycle || {};`, babylonConfig as any)()); // 硬核植入快應(yīng)用生命周期
        node.body.push(template(`export default Object.assign(require('${taroMiniAppFrameworkPath}').default.createApp(${exportVariableName}),quickappLifecycle)`, babylonConfig as any)())
    } else {
        node.body.push(template(`App(require('${taroMiniAppFrameworkPath}').default.createApp(${exportVariableName}))`, babylonConfig as any)())
    }
    node.body.push(template(`Taro.initPxTransform(${JSON.stringify(pxTransformConfig)})`, babylonConfig as any)())
    break
復(fù)制代碼
// app.quickapp.js

quickappLifecycle.onShow = () => {
  // 業(yè)務(wù)代碼
}

quickappLifecycle.onHide = () => {
  // 業(yè)務(wù)代碼
}
復(fù)制代碼

生成的代碼

// app.ux 底部

exports.default = Object.assign(require('./npm/@tarojs/taro-quickapp/index.js').default.createApp(_App), quickappLifecycle);

_index2.default.initPxTransform({
  "designWidth": 750,
  "deviceRatio": {
    "640": 1.17,
    "750": 1,
    "828": 0.905
  }
});
script>
復(fù)制代碼

重點(diǎn)說(shuō)明:我們的目的只要做到最后我們編譯后生成的代碼中,exports.default 導(dǎo)出的 JS 對(duì)象,是被我們賦值了新的生命周期方法即可。

查看 Taro 源碼發(fā)現(xiàn)編譯后的代碼,是由其 @tarojs/cli/src/mini/astProcess.ts 文件生成的,而且他的生成模板都是固定的,那么就動(dòng)點(diǎn)小手腳,在模板頂部插入一個(gè)變量

node.body.unshift(template(`var quickappLifecycle = global.quickappLifecycle || {};`, babylonConfig as any)()); // 硬核植入快應(yīng)用生命周期
復(fù)制代碼

然后再在模板輸出的地方將變量合并到輸出模塊中

 node.body.push(template(`export default Object.assign(require('${taroMiniAppFrameworkPath}').default.createApp(${exportVariableName}),quickappLifecycle)`, babylonConfig as any)())
復(fù)制代碼

那么對(duì)于開(kāi)發(fā)來(lái)說(shuō),只需要在業(yè)務(wù)代碼中,正常的將生命周期掛載到變量就好了

// app.quickapp.js

quickappLifecycle.onShow = () => {
  // app顯示的業(yè)務(wù)代碼
}

quickappLifecycle.onHide = () => {
  // app隱藏的業(yè)務(wù)代碼
}
復(fù)制代碼

以上的攔截都是比較粗暴的覆蓋形式,可以做更細(xì)的優(yōu)化就不展開(kāi)了,同時(shí)其他的頁(yè)面級(jí)別的生命周期攔截方式也是類似的,就不繼續(xù)展開(kāi)了。

全局的錯(cuò)誤監(jiān)控

以上我們已經(jīng)基本摸清了 Taro 的生命周期原理,那么就做一個(gè)簡(jiǎn)單的業(yè)務(wù)實(shí)踐。應(yīng)用的全局錯(cuò)誤監(jiān)控照道理是每一個(gè)應(yīng)用都應(yīng)該要有的,以下的代碼片段是我們分別對(duì)小程序和快應(yīng)用做的全局生命周期攔截。業(yè)務(wù)代碼沒(méi)有摘錄(小程序可以直接對(duì)接微信平臺(tái),快應(yīng)用可以對(duì)接輕粒子),建議將錯(cuò)誤日志對(duì)接到內(nèi)部的錯(cuò)誤日志平臺(tái)上,通過(guò)平臺(tái)可以做很多的數(shù)據(jù)分析,以及預(yù)警機(jī)制,從而來(lái)保障我們的應(yīng)用穩(wěn)定。

// app.quickapp.js
/** 錯(cuò)誤攔截捕獲 */

function catchError() {
  if (process.env.TARO_ENV == 'weapp') {
    // 小程序生命周期攔截
    const _originApp = App

    App = function (options) {
      const _options = { ...options }

      _options.onUnhandledRejection = (err) => {
        console.error(err && (err.reason ? err.reason : err))
      }

      _options.onError = (err) => {
        console.error(err)
      }

      return _originApp(_options)
    }
  }

  if (process.env.TARO_ENV == 'quickapp') {
    // 快應(yīng)用生命周期攔截
    // 監(jiān)聽(tīng) promise 錯(cuò)誤
    if (global.QuickApp) {
      global.QuickApp.unhandledrejection = (index, stack, message) => {
        try {
          console.error({
            stack,
            message,
          })
        } catch (error) {
          console.log('unhandledrejection', error)
        }
      }
    } // 監(jiān)聽(tīng) onError

    quickappLifecycle.onError = (err) => {
      try {
        console.log('onError', err)
      } catch (error) {
        console.log('onError', error)
      }
    }
  }
}

try {
  catchError()
} catch (error) {}
復(fù)制代碼

最后

摸清 Taro 生命周期實(shí)現(xiàn)原理后,Taro 轉(zhuǎn)快應(yīng)用的那些事兒就更明白了。


作者:beezend
來(lái)源:掘金
著作權(quán)歸作者所有。商業(yè)轉(zhuǎn)載請(qǐng)聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請(qǐng)注明出處。

相關(guān)案例查看更多