资讯专栏INFORMATION COLUMN

在小程序中实现 Mixins 方案

chunquedong / 2541人阅读

摘要:明白了什么是以后,便可开始着手在小程序里面实现了。但是在小程序中,这套机制会和的有一点区别。代码实现在小程序中,每个页面都由函数定义,而则作用于这个函数当中的对象。函数即为小程序运行机制的具体实现,完全按照上一节总结的三条结论来进行。

原文来自我的博客:https://jrainlau.github.io/#/...

在原生开发小程序的过程中,发现有多个页面都使用了几乎完全一样的逻辑。由于小程序官方并没有提供 Mixins 这种代码复用机制,所以只能采用非常不优雅的复制粘贴的方式去“复用”代码。随着功能越来越复杂,靠复制粘贴来维护代码显然不科学,于是便寻思着如何在小程序里面实现 Mixins。

什么是 Mixins

Mixins 直译过来是“混入”的意思,顾名思义就是把可复用的代码混入当前的代码里面。熟悉 VueJS 的同学应该清楚,它提供了更强大了代码复用能力,解耦了重复的模块,让系统维护更加方便优雅。

先看看在 VueJS 中是怎么使用 Mixins 的。

// 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 的方法了。

明白了什么是 Mixins 以后,便可开始着手在小程序里面实现了。

Mixins 的机制

Mixins 也有一些小小的细节需要注意的,就是关于生命周期事件的执行顺序。在上一节的例子中,我们在 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 的 log,再输出来自组件的 log。

除了生命周期函数以外,再看看对象属性的混入结果:

// 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()

在 VueJS 中,会把来自 Mixins 和组件的对象属性当中的内容(如 data, methods等)混合,以确保两边的数据都同时存在。

经过上述的验证,我们可以得到 VueJS 中关于 Mixins 运行机制的结论:

生命周期属性,会优先执行来自 Mixins 当中的,后执行来自组件当中的。

对象类型属性,来自 Mixins 和来自组件中的会共存。

但是在小程序中,这套机制会和 VueJS 的有一点区别。在小程序中,自定义的方法是直接定义在 Page 的属性当中的,既不属于生命周期类型属性,也不属于对象类型属性。为了不引入奇怪的问题,我们为小程序的 Mixins 运行机制多加一条:

小程序中的自定义方法,优先级为 Page > Mixins,即 Page 中的自定义方法会覆盖 Mixins 当中的。

代码实现

在小程序中,每个页面都由 Page(options) 函数定义,而 Mixins 则作用于这个函数当中的 options 对象。因此我们实现 Mixins 的思路就有了——劫持并改写 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)
}

原理很简单,关键的地方在于 merge() 函数。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 里引入 mixins.js

require("./mixins.js")

撰写一个 myMixin.js

module.exports = {
  data: { someData: "myMixin" },
  onShow () { console.log("Log from mixin!") }
}

page/index/index.js 中使用

Page({
  mixins: [require("../../myMixin.js")]
})

大功告成!此时小程序已经具备 Mixins 的能力,对于代码解耦与复用来说将会更加方便。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/104845.html

相关文章

  • 程序开发经验:多页面数据同步

    摘要:监听点赞事件广播重点在这里我的动态页面收到点赞变化通知进行更新操作监听发布事件广播重点在这里我的动态页面收到发布动态通知进行更新操作重点在这里至此,我们在小程序中完美的实现了跨页面组件多页面数据同步。 导语:本文主要介绍在小程序中,多页面之间如何保持数据同步 在很多的产品中,都会存在跨页面间需要数据同步,如下示例: showImg(https://user-gold-cdn.xitu.io...

    mudiyouyou 评论0 收藏0
  • 微信小程序开发中的二三事之网易云信IMSDK DEMO

    摘要:传统的网页编程采用的三剑客来实现,在微信小程序中同样有三剑客。观察者模式不难实现,重点是如何在微信小程序中搭配其特有的生命周期来使用。交互事件传统的事件传递类型有冒泡型与捕获型,微信小程序中自然也有。 本文由作者邹永胜授权网易云社区发布。 简介为了更好的展示我们即时通讯SDK强悍的能力,网易云信IM SDK微信小程序DEMO的开发就提上了日程。用产品的话说就是: 云信 IM 小程序 S...

    weij 评论0 收藏0
  • 演示在小程序中实excel数据的批量导入的具体代码

      其实我们本篇文章主要讲述的就是需要将采集的数据积累下来,变成企业的数字资产。  积累数据最好的方式就是把数据存入数据库,低码工具除了有可视化编程的便利外,不仅如此还有提供了线上的文档型数据库。文档数据库相比传统数据库,文档数据库的返回结构是JSON格式,直接就可以在前端进行渲染。关系型数据库还得通过代码进行转译。  我们现在还讲另外一个方面是文档数据库的类型更丰富,有附件、富文本、自动编号、数...

    3403771864 评论0 收藏0
  • 客户端数据存储概述

    过去十年中,浏览器已经发展成为一个强大的工具。这是一个缓慢的过程,伴随着许多成长之痛。现在,增强型布局控件、3D图形和游戏,甚至是音乐都可以在小而古老的浏览器中实现。客户端数据存储是一个更加令人兴奋的特性。 浏览Web的经典过程从一开始就没有变过:浏览器请求一个URL,Web服务器返回请求的内容,然后浏览器请求更多的内容,而服务器返回更多的内容。浏览器似乎很健忘,它知道的所有东西都必须从服务器获得...

    付永刚 评论0 收藏0

发表评论

0条评论

chunquedong

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<