国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > JavaScript > 正文

微信小程序開發教程之增加mixin擴展

2019-11-19 15:51:30
字體:
來源:轉載
供稿:網友

Mixin簡介

Mixin(織入)模式并不是GOF的《設計模式》歸納中的一種,但是在各種語言以及框架都會發現該模式(或者思想)的一些應用。簡單來說,Mixin是帶有全部實現或者部分實現的接口,其主要作用是更好的代碼復用。

Mixin這個概念在React, Vue中都有支持,它為我們抽象業務邏輯,代碼復用提供了方便。然而小程序原生框架并沒直接支持Mixin。我們先看一個很實際的需求:

為所有小程序頁面增加運行環境class,以方便做一些樣式hack。具體說就是小程序在不同的運行環境(開發者工具|iOS|Android)運行時,platform值為對應的運行環境值("ios|android|devtools")

<view class="{{platform}}"> <!--頁面模板--></view>

回顧vue中mixin的使用

文章開始提到的問題是非常適合使用Mixin來解決的。我們把這個需求轉換成一個Vue問題:在每個路由頁面中增加一個platform的樣式class(雖然這樣做可能沒實際意義)。實現思路就是為每個路由組件增加一個data: platform。代碼實現如下:

// mixins/platform.jsconst getPlatform = () => { // 具體實現略,這里mock返回'ios' return 'ios';};export default { data() { return {  platform: getPlatform() } }}
// 在路由組件中使用// views/index.vueimport platform from 'mixins/platform';export default { mixins: [platform], // ...}
// 在路由組件中使用// views/detail.vueimport platform from 'mixins/platform';export default { mixins: [platform], // ...}

這樣,在index,detail兩個路由頁的viewModel上就都有platform這個值,可以直接在模板中使用。

vue中mixin分類

  • data mixin
  • normal method mixin
  • lifecycle method mixin

用代碼表示的話,就如:

export default { data () { return {  platform: 'ios' } }, methods: { sayHello () {  console.log(`hello!`) } }, created () { console.log(`lifecycle3`) }}

vue中mixin合并,執行策略

如果mixin間出現了重復,這些mixin會有具體的合并,執行策略。如下圖:

如何讓小程序支持mixin

在前面,我們回顧了vue中mixin的相關知識。現在我們要讓小程序也支持mixin,實現vue中一樣的mixin功能。

實現思路

我們先看一下官方的小程序頁面注冊方式:

Page({ data: { text: "This is page data." }, onLoad: function(options) { // Do some initialize when page load. }, onReady: function() { // Do something when page ready. }, onShow: function() { // Do something when page show. }, onHide: function() { // Do something when page hide. }, onUnload: function() { // Do something when page close. }, customData: { hi: 'MINA' }})

假如我們加入mixin配置,上面的官方注冊方式會變成:

Page({ mixins: [platform], data: { text: "This is page data." }, onLoad: function(options) { // Do some initialize when page load. }, onReady: function() { // Do something when page ready. }, onShow: function() { // Do something when page show. }, onHide: function() { // Do something when page hide. }, onUnload: function() { // Do something when page close. }, customData: { hi: 'MINA' }})

這里有兩個點,我們要特別注意:

  • Page(configObj) - 通過configObj配置小程序頁面的data, method, lifecycle等
  • onLoad方法 - 頁面main入口

要想讓mixin中的定義有效,就要在configObj正式傳給Page()之前做文章。其實Page(configObj)就是一個普通的函數調用,我們加個中間方法:

Page(createPage(configObj))

在createPage這個方法中,我們可以預處理configObj中的mixin,把其中的配置按正確的方式合并到configObj上,最后交給Page() 。這就是實現mixin的思路。

具體實現

具體代碼實現就不再贅述,可以看下面的代碼。更詳細的代碼實現,更多擴展,測試可以參看github

/** * 為每個頁面提供mixin,page invoke橋接 */const isArray = v => Array.isArray(v);const isFunction = v => typeof v === 'function';const noop = function () {};// 借鑒redux https://github.com/reactjs/reduxfunction compose(...funcs) { if (funcs.length === 0) { return arg => arg; } if (funcs.length === 1) { return funcs[0]; } const last = funcs[funcs.length - 1]; const rest = funcs.slice(0, -1); return (...args) => rest.reduceRight((composed, f) => f(composed), last(...args));}// 頁面堆棧const pagesStack = getApp().$pagesStack;const PAGE_EVENT = ['onLoad', 'onReady', 'onShow', 'onHide', 'onUnload', 'onPullDownRefresh', 'onReachBottom', 'onShareAppMessage'];const APP_EVENT = ['onLaunch', 'onShow', 'onHide', 'onError'];const onLoad = function (opts) { // 把pageModel放入頁面堆棧 pagesStack.addPage(this); this.$invoke = (pagePath, methodName, ...args) => { pagesStack.invoke(pagePath, methodName, ...args); }; this.onBeforeLoad(opts); this.onNativeLoad(opts); this.onAfterLoad(opts);};const getMixinData = mixins => { let ret = {}; mixins.forEach(mixin => { let { data={} } = mixin; Object.keys(data).forEach(key => {  ret[key] = data[key]; }); }); return ret;};const getMixinMethods = mixins => { let ret = {}; mixins.forEach(mixin => { let { methods={} } = mixin; // 提取methods Object.keys(methods).forEach(key => {  if (isFunction(methods[key])) {  // mixin中的onLoad方法會被丟棄  if (key === 'onLoad') return;  ret[key] = methods[key];  } }); // 提取lifecycle PAGE_EVENT.forEach(key => {  if (isFunction(mixin[key]) && key !== 'onLoad') {  if (ret[key]) {   // 多個mixin有相同lifecycle時,將方法轉為數組存儲   ret[key] = ret[key].concat(mixin[key]);  } else {   ret[key] = [mixin[key]];  }  } }) }); return ret;};/** * 重復沖突處理借鑒vue: * data, methods會合并,組件自身具有最高優先級,其次mixins中后配置的mixin優先級較高 * lifecycle不會合并。先順序執行mixins中的lifecycle,再執行組件自身的lifecycle */const mixData = (minxinData, nativeData) => { Object.keys(minxinData).forEach(key => { // page中定義的data不會被覆蓋 if (nativeData[key] === undefined) {  nativeData[key] = minxinData[key]; } }); return nativeData;};const mixMethods = (mixinMethods, pageConf) => { Object.keys(mixinMethods).forEach(key => { // lifecycle方法 if (PAGE_EVENT.includes(key)) {  let methodsList = mixinMethods[key];  if (isFunction(pageConf[key])) {  methodsList.push(pageConf[key]);  }  pageConf[key] = (function () {  return function (...args) {   compose(...methodsList.reverse().map(f => f.bind(this)))(...args);  };  })(); } // 普通方法 else {  if (pageConf[key] == null) {  pageConf[key] = mixinMethods[key];  } } }); return pageConf;};export default pageConf => { let { mixins = [], onBeforeLoad = noop, onAfterLoad = noop } = pageConf; let onNativeLoad = pageConf.onLoad || noop; let nativeData = pageConf.data || {}; let minxinData = getMixinData(mixins); let mixinMethods = getMixinMethods(mixins); Object.assign(pageConf, { data: mixData(minxinData, nativeData), onLoad, onBeforeLoad, onAfterLoad, onNativeLoad, }); pageConf = mixMethods(mixinMethods, pageConf); return pageConf;};

小結

1、本文主要講了如何為小程序增加mixin支持。實現思路為:預處理configObj

Page(createPage(configObj))

2、在處理mixin重復時,與vue保持一致:

      data, methods會合并,組件自身具有最高優先級,其次mixins中后配置的mixin優先級較高。

      lifecycle不會合并。先順序執行mixins中的lifecycle,再執行組件自身的lifecycle。

總結

好了,以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作能帶來一定的幫助,如果有疑問大家可以留言交流,謝謝大家對武林網的支持。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 九江县| 鄢陵县| 太原市| 金溪县| 五常市| 剑河县| 陆川县| 新密市| 泰来县| 新余市| 泸溪县| 岐山县| 石泉县| 游戏| 齐齐哈尔市| 大姚县| 高邮市| 元谋县| 淳安县| 顺平县| 雷州市| 花莲县| 温泉县| 伊金霍洛旗| 板桥市| 巴楚县| 金山区| 济阳县| 五寨县| 正镶白旗| 湘乡市| 宝兴县| 方山县| 定日县| 广平县| 邯郸市| 津市市| 肃宁县| 华安县| 恩平市| 湘潭市|