如何在微信小程序中实现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 相关文章推荐
javascript下查找父节点的简单方法
Aug 13 Javascript
创建公共调用 jQuery Ajax 带返回值
Aug 01 Javascript
jquery解决图片路径不存在执行替换路径
Feb 06 Javascript
用jquery生成二级菜单的实例代码
Jun 24 Javascript
使用indexOf等在JavaScript的数组中进行元素查找和替换
Sep 18 Javascript
JQuery处理json与ajax返回JSON实例代码
Jan 03 Javascript
bootstrap配合Masonry插件实现瀑布式布局
Jan 18 Javascript
JavaScript实现三级联动菜单实例代码
Jun 26 Javascript
详述 Sublime Text 打开 GBK 格式中文乱码的解决方法
Oct 26 Javascript
对vux点击事件的优化详解
Aug 28 Javascript
使用ng-packagr打包Angular的方法示例
Sep 21 Javascript
JavaScript快速调试的两个技巧
Nov 04 Javascript
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
星际中一些鲜为人知的详细资料
2020/03/04 星际争霸
收集的php编写大型网站问题集
2007/03/06 PHP
ThinkPHP模板范围判断输出In标签与Range标签用法详解
2014/06/30 PHP
PHP安装memcached扩展笔记
2015/05/28 PHP
JavaScript与HTML结合的基本使用方法整理
2015/10/12 PHP
PHP文件上传问题汇总(文件大小检测、大文件上传处理)
2015/12/24 PHP
win10环境PHP 7 安装配置【教程】
2016/05/09 PHP
PHP中的表达式简述
2016/05/29 PHP
php处理抢购类功能的高并发请求
2018/02/08 PHP
JQuery 确定css方框模型(盒模型Box Model)
2010/01/22 Javascript
根据选择不同的下拉值出现相对应的文本输入框
2013/08/01 Javascript
jquery改变disabled的boolean状态的三种方法
2013/12/13 Javascript
JQuery中使文本框获得焦点的方法实例分析
2015/02/28 Javascript
JS使用parseInt解析数字实现求和的方法
2015/08/05 Javascript
jquery实现美观的导航菜单鼠标提示特效代码
2015/09/06 Javascript
jquery实现仿新浪微博带动画效果弹出层代码(可关闭、可拖动)
2015/10/12 Javascript
初识angular框架后的所思所想
2016/02/19 Javascript
全面了解JavaScript对象进阶
2016/07/19 Javascript
使用纯JS代码判断字符串中有多少汉字的实现方法(超简单实用)
2016/11/12 Javascript
深入理解jquery中extend的实现
2016/12/22 Javascript
微信小程序 高德地图SDK详解及简单实例(源码下载)
2017/01/11 Javascript
Bootstrap Scrollspy源码学习
2017/03/02 Javascript
CSS3+JavaScript实现翻页幻灯片效果
2017/06/28 Javascript
Angular4的输入属性与输出属性实例详解
2017/11/29 Javascript
react-native 圆弧拖动进度条实现的示例代码
2018/04/12 Javascript
JS隐藏号码中间4位代码实例
2019/04/09 Javascript
javascript解析json格式的数据方法详解
2020/08/07 Javascript
[48:00]完美世界DOTA2联赛循环赛 Forest vs Inki BO2第二场 11.04
2020/11/04 DOTA
python获取本地计算机名字的方法
2015/04/29 Python
基于Python中求和函数sum的用法详解
2018/06/28 Python
通过python的matplotlib包将Tensorflow数据进行可视化的方法
2019/01/09 Python
一篇文章搞定Python操作文件与目录
2019/08/13 Python
简单易懂Pytorch实战实例VGG深度网络
2019/08/27 Python
python set集合使用方法解析
2019/11/05 Python
Python内建序列通用操作6种实现方法
2020/03/26 Python
环境工程毕业生自荐信
2013/11/17 职场文书