2.总结微信小程序9个优雅小技巧-(混入)复用属性/方法

例子: https://gitee.com/akff/ak-mini-program

实现效果: 无需重复定义,自动导入对应参数


image.png

核心代码

// 1. 手动混入
/**
 * 例子: (需要混入的页面中)
 * import initMixin from './mixin'
 * import 混入js from './js代码'
 * const mixin = initMixin()
 * mixin.use(引用混入js文件)
 * mixin.Page({
 *    data: {}
 *    onLoad: function(){
 *    }
 * })
 */

// 2. 全局混入
/**
 * 例子: (在app.js中执行, 也可导入已封装好的global-mixin.js)
 * import initMixin from './mixin'
 * // 混入-基础数据(可选)
 * import pageData from './global/pageData'
 * mixin(pageData)
 * // 注意:替换掉原Page方法
 * Page = mixin.Page
 */


const originApp = App
const originPage = Page
const originComponent = Component

// 混入-基础数据
import pageData from './global/pageData'

function init(...mixinFun) {
  // 可以用于拓展的生命周期
  const life = {
    App: ['preprocess', 'onLaunch', 'onShow', 'onHide', 'onError'],
    Page: ['preprocess', 'onLoad', 'onReady', 'onShow', 'onHide', 'onUnload', 'onPullDownRefresh', 'onReachBottom', 'onShareAppMessage'],
    Component: ['preprocess', 'created', 'attached', 'ready', 'moved', 'detached', 'error']
  };

  // 用于保存所有的拓展生命周期函数
  let lifeMixin = {};
  for (let key in life) {
    lifeMixin[key] = lifeMixin[key] || {};
    for (let lifeTime of life[key]) {
      lifeMixin[key][lifeTime] = [];
    }
  }

  // 基类对象
  // 在调用App、Page、Component前会被混入到对象中
  let base = {
    App: {},
    Page: {},
    Component: {}
  }

  let MpExtend = function (param) {
    // 允许接收数组形式的参数
    if (isArray(param)) {
      param.forEach(item => MpExtend(item));
      return;
    }

    for (const constructorName in param) {
      // constructorName 应当是[App, Page, Component] 中的一个
      if (!life[constructorName]) {
        warning(constructorName, 'not found');
        continue;
      }

      const option = Object.assign({}, param[constructorName]);
      // 如果是生命周期中的某一个,作为生命周期拓展
      for (const key in option) {
        if (lifeMixin[constructorName][key]) {
          lifeMixin[constructorName][key].push(option[key]);
          delete option[key];
        }
      }
      // 把剩余的属性混入到基类中
      mixin(base[constructorName], option);
    }
  }

  // 重新包装的 App、Page、Component构造函数
  // 虽然都是相似的代码但是这样更利于理解和修改
  const _App = decorate(originApp, function (option) {
    mixin(option, base.App);
    for (const lifeTime of life.App) {
      option[lifeTime] = decorate(option[lifeTime], ...lifeMixin.App[lifeTime]);
    }
    option['preprocess'] && option['preprocess'].call(option, option);
  });
  const _Page = decorate(originPage, function (option) {
    mixin(option, base.Page);
    for (const lifeTime of life.Page) {
      option[lifeTime] = decorate(option[lifeTime], ...lifeMixin.Page[lifeTime]);
    }
    option['preprocess'] && option['preprocess'].call(option, option);
  });
  const _Component = decorate(originComponent, function (option) {
    mixin(option, base.Component);
    for (const lifeTime of life.Component) {
      option[lifeTime] = decorate(option[lifeTime], ...lifeMixin.Component[lifeTime]);
    }
    option['preprocess'] && option['preprocess'].call(option, option);
  });

  // 装饰函数
  // 在调用原函数之前调用所有装饰器
  function decorate(f, ...decorators) {
    return function () {
      for (const decorator of decorators) {
        decorator && decorator.apply(this, arguments);
      }
      return f && f.apply(this, arguments);
    };
  }

  /**
   * 实现类似混入的效果
   * 类似 Object.assign, 但在遇见相同属性名均是对象时会递归进行合并而非直接覆盖
   * @param o
   * @param mix 可以传入多个
   * 注:如果存在引用循环递归会栈溢出
   */
  function mixin(o, ...mixs) {
    mixs.forEach(mix => {
      for (const key in mix) {
        // 两个属性都是对象则递归合并
        if (isObject(o[key]) && isObject(mix[key])) {
          mixin(o[key], mix[key]);
        } else {
          o[key] = o[key] || mix[key];
        }
      }
      // 拷贝symbol类型,(可惜小程序不支持)
      for (const sym of Object.getOwnPropertySymbols(mix)) {
        o[sym] = o[sym] || mix[sym];
      }
    });
    return o;
  }

  function isObject(o) {
    return Object.prototype.toString.call(o) === "[object Object]";
  }

  function isArray(o) {
    return Object.prototype.toString.call(o) === "[object Array]";
  }

  function warning(...msg) {
    MpExtend.tips && console.warn('ak-mp-extend:', ...msg);
  }

  Object.assign(MpExtend, {
    mixin,
    decorate,
    lifeMixin,
    App: _App,
    Page: _Page,
    Component: _Component,
    warning,
    init,
    tips: true
  });
  // 遍历混入
  for(let item of mixinFun){
    MpExtend(item)
  }
  // 混入基础方法
  MpExtend(pageData)
  return MpExtend
}
// let MpExtend = init()
export default init;

方式一: 混入所有界面对象

  1. 在app.js中执行以下代码, 也可导入已封装好的global-mixin.js
// global-mixin.js
// 核心JS
import initMixin from './mixin'
 // 混入-基础数据(可选)
import pageData from './global/pageData'
mixin(pageData)
// 注意:替换掉原Page方法
Page = mixin.Page

方式二: 手动混入,在对应界面混入

        import initMixin from '../../../utils/mixins/mixin'
        import pageData from '../../../utils/mixins/global/pageData'
        const mixin = initMixin(pageData)
        
        mixin.Page({
          /**
           * 页面的初始数据
           */
          data: {},
          onLoad(options) {}
        })  

例子: https://gitee.com/akff/ak-mini-program

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,463评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,868评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,213评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,666评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,759评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,725评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,716评论 3 415
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,484评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,928评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,233评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,393评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,073评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,718评论 3 324
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,308评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,538评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,338评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,260评论 2 352

推荐阅读更多精彩内容