如何在微信小程序中实现Mixins方案


Posted in Javascript onJune 20, 2019

前言

在原生开发小程序的过程中,发现有多个页面都使用了几乎完全一样的逻辑。由于小程序官方并没有提供 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()

如何在微信小程序中实现Mixins方案

在 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 注入并执行相应逻辑
 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 }
  }
 }
 })
}

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方案

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

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对三水点靠木的支持。

Javascript 相关文章推荐
一段利用WSH修改和查看IP配置的代码
May 11 Javascript
extjs fckeditor集成代码
May 10 Javascript
jQuery选择头像并实时显示的代码
Jun 27 Javascript
Jquery效果大全之制作电脑健康体检得分特效附源码下载
Nov 02 Javascript
jQuery控制控件文本的长度的操作方法
Dec 05 Javascript
jQuery动态生成表格及右键菜单功能示例
Jan 13 Javascript
Android中Okhttp3实现上传多张图片同时传递参数
Feb 18 Javascript
Angular.js中window.onload(),$(document).ready()的写法浅析
Sep 28 Javascript
Vue使用lodop实现打印小结
Jul 06 Javascript
node.js中stream流中可读流和可写流的实现与使用方法实例分析
Feb 13 Javascript
vue 解决兄弟组件、跨组件深层次的通信操作
Jul 27 Javascript
vue实现无缝轮播效果(跑马灯)
May 14 Vue.js
js JSON.stringify()基础详解
Jun 19 #Javascript
使用jquery-easyui的布局layout写后台管理页面的代码详解
Jun 19 #jQuery
Vue-Cli 3.0 中配置高德地图的两种方式
Jun 19 #Javascript
vue axios重复点击取消上一次请求封装的方法
Jun 19 #Javascript
javascript创建元素和删除元素实例小结
Jun 19 #Javascript
Vue 2.0 侦听器 watch属性代码详解
Jun 19 #Javascript
js获取对象,数组所有属性键值(key)和对应值(value)的方法示例
Jun 19 #Javascript
You might like
Php Mssql操作简单封装支持存储过程
2009/12/11 PHP
PHP高级编程实例:编写守护进程
2014/09/02 PHP
php生成随机数的三种方法
2014/09/10 PHP
PHP利用header跳转失效的解决方法
2014/10/24 PHP
thinkPHP2.1自定义标签库的导入方法详解
2016/07/20 PHP
PHP中的日期时间处理利器实例(Carbon)
2017/06/09 PHP
PHP通过GD库实现验证码功能示例
2019/02/23 PHP
php常用经典函数集锦【数组、字符串、栈、队列、排序等】
2019/08/23 PHP
jquery操作复选框(checkbox)的12个小技巧总结
2014/02/04 Javascript
使用jquery操作session方法分享
2015/01/22 Javascript
测试IE浏览器对JavaScript的AngularJS的兼容性
2015/06/19 Javascript
仅9张思维导图帮你轻松学习Javascript 就这么简单
2016/06/01 Javascript
轻松理解Javascript变量的相关问题
2017/01/20 Javascript
详解vue-resource promise兼容性问题
2017/06/20 Javascript
Javascript中将变量转换为字符串的三种方法
2017/09/19 Javascript
js canvas画布实现高斯模糊效果
2018/11/27 Javascript
原生JS实现贪吃蛇小游戏
2020/03/09 Javascript
Jquery $.map使用方法实例详解
2020/09/01 jQuery
[01:51]历届DOTA2国际邀请赛举办地回顾 TI9落地上海
2018/08/26 DOTA
[48:46]完美世界DOTA2联赛PWL S2 SZ vs FTD.C 第二场 11.19
2020/11/19 DOTA
Python之eval()函数危险性浅析
2014/07/03 Python
python脚本实现分析dns日志并对受访域名排行
2014/09/18 Python
python清除字符串里非字母字符的方法
2015/07/02 Python
Python提取Linux内核源代码的目录结构实现方法
2016/06/24 Python
Python3 处理JSON的实例详解
2017/10/29 Python
机器学习实战之knn算法pandas
2019/06/22 Python
python GUI库图形界面开发之PyQt5图片显示控件QPixmap详细使用方法与实例
2020/02/27 Python
最新大学生创业计划书写作攻略
2014/04/02 职场文书
生物科学专业毕业生求职信
2014/06/02 职场文书
安全伴我行演讲稿
2014/09/04 职场文书
公司聚餐通知
2015/04/22 职场文书
考生诚信考试承诺书
2015/04/29 职场文书
导游词之峨眉山
2019/12/16 职场文书
python非标准时间的转换
2021/07/25 Python
Java实现经典游戏泡泡堂的示例代码
2022/04/04 Java/Android
golang三种设计模式之简单工厂、方法工厂和抽象工厂
2022/04/10 Golang