Code前端首页关于Code前端联系我们

小程序原生开发中实现mixins代码复用机制的解决方案

terry 2年前 (2023-09-23) 阅读数 69 #移动小程序

在小程序原生开发的过程中,我发现不同的页面使用了几乎相同的逻辑。由于小程序官方并没有提供像 mixins 这样的代码重用机制,所以“重用”代码的唯一方法就是通过非常不优雅的复制粘贴方法。随着功能越来越复杂,通过复制粘贴来维护代码显然是不科学的,于是我开始思考如何在小程序中实现mixin。

什么是 Mixins

Mixin 的字面意思是“混合”。顾名思义,这意味着将可重用代码混合到当前代码中。熟悉VueJS的同学应该知道,它提供了更强大的代码复用能力,解耦了重复模块,让系统维护更加方便优雅。

我们先来看看如何在 VueJS 中使用 mixin。

// define a mixin object
var myMixin = {
  created: function () {
    this.hello()
  },
  methods: {
    hello: function () {
      console.log('hello from mixin!')
    }
  }
}

// define a component that uses this mixin
var Component = Vue.extend({
  mixins: [myMixin]
})

var component = new Component() // => "hello from mixin!"
复制代码

上面的代码中,首先定义了一个名为myMixin的对象,该对象定义了一些生命周期函数和方法。然后将它们直接注入到mixins新建的组件中:[myMixin]。这时,新创建的组件就会有myMixin的方法。

了解了什么是 mixin 后,就可以开始将它们实现到小程序中了。

Mixin 的机制

Mixin 还有一些小细节需要注意,那就是生命周期事件的执行顺序。在上一节的例子中,我们在myMixin中定义了一个created()方法,它是VueJS中的生命周期事件。如果我们在新组件Component中也定义一个created()方法,那么执行结果会是什么呢?

var Component = Vue.extend({
  mixins: [myMixin],
  created: function () {
    console.log('hello from Component!')
  }
})

var component = new Component()

// =>
// Hello from mixin!
// Hello from Component!
复制代码

可以看到运行结果是先输出mixin的日志,然后输出组件的日志。

除了生命周期功能之外,我们再看一下对象属性的混合结果:

// define a mixin object
const myMixin = {
  data () {
    return {
      mixinData: 'data from mixin'
    }
  }
}

// define a component that uses this mixin
var Component = Vue.extend({
  mixins: [myMixin],
  data () {
    return {
      componentData: 'data from component'
    }
  },
  mounted () {
    console.log(this.$data)
  }
})

var component = new Component()
复制代码
原生开发小程序中实现 Mixins 代码复用机制方案

在VueJS中,mixin和组件的对象属性的内容(如data❓、方法等)混合使用,保证双方数据同时存在。

经过上面的验证,我们可以得到VueJS中mixins的运行机制的结论:

  1. 生命周期属性是先由mixins执行,然后由组件执行。
  2. mixin 和组件的对象类型属性将共存。

但是在小程序中,这个机制会和VueJS有点不同。在小程序中,自定义方法直接定义在页面的属性中,它既不是生命周期类型属性,也不是对象类型属性。为了不引入奇怪的问题,我们在小程序的 mixins 运行机制中额外添加一行:

  1. 小程序中自定义方法的优先级为 Page > Mixins,即自定义方法对 Page 进行覆盖Mixins 中的那些。

代码实现

小程序中,每个页面由Page(Options)函数定义,mixin作用于Options对象。所以我们实现mixin的思路就是劫持函数Page并重写,最后再次释放。

新建一个mixins.js文件:

// 保存原生的 Page 函数
const originPage = Page

Page = (options) => {
  const mixins = options.mixins
  // mixins 必须为数组
  if (Array.isArray(mixins)) {
    delete options.mixins
    // mixins 注入并执行相应逻辑
    options = merge(mixins, options)
  }
  // 释放原生 Page 函数
  originPage(options)
}
复制代码

原理很简单,关键点就是fusion()♶❝。函数merge是小程序Mixins运行机制的具体实现,完全按照上一节总结的三个结论来进行。

// 定义小程序内置的属性/方法
const originProperties = ['data', 'properties', 'options']
const originMethods = ['onLoad', 'onReady', 'onShow', 'onHide', 'onUnload', 'onPullDownRefresh', 'onReachBottom', 'onShareAppMessage', 'onPageScroll', 'onTabItemTap']

function merge (mixins, options) {
  mixins.forEach((mixin) => {
    if (Object.prototype.toString.call(mixin) !== '[object Object]') {
      throw new Error('mixin 类型必须为对象!')
    }
    // 遍历 mixin 里面的所有属性
    for (let [key, value] of Object.entries(mixin)) {
      if (originProperties.includes(key)) {
        // 内置对象属性混入
        options[key] = { ...value, ...options[key] }
      } else if (originMethods.includes(key)) {
        // 内置方法属性混入,优先执行混入的部分
        const originFunc = options[key]
        options[key] = function (...args) {
          value.call(this, ...args)
          return originFunc && originFunc.call(this, ...args)
        }
      } else {
        // 自定义方法混入
        options = { ...mixin, ...options }
      }
    }
  })
  return options
}
复制代码

Mixins 在小程序app.js中使用

  1. 引入mixins.js
require('./mixins.js')
复制代码
  1. 来引入m❓s。 位于 页面 /index 在 /index.js
中使用

Page({
  mixins: [require('../../myMixin.js')]
})
复制代码
原生开发小程序中实现 Mixins 代码复用机制方案

即可完成!此时小程序已经具备了mixins的能力,更方便代码解耦和复用。

作者:Jrain
链接:https://juejin.im/post/5d0a07eb6fb9a07eba2c4142
来源:掘金
版权归作者所有。如需商业转载,请联系求作者授权。非商业转载请来源。

版权声明

本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

热门