如何在微信小程序中实现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 相关文章推荐
jQuery.fn和jQuery.prototype区别介绍
Oct 05 Javascript
jQuery实现预加载图片的方法
Mar 17 Javascript
Javascript获取随机数的实现方法
Jun 22 Javascript
jQuery实现移动端手机商城购物车功能
Sep 24 Javascript
微信小程序 购物车简单实例
Oct 24 Javascript
基于MVC方式实现三级联动(JavaScript)
Jan 23 Javascript
JS基于正则截取替换特定字符之间字符串操作示例
Feb 03 Javascript
十大热门的JavaScript框架和库
Mar 21 Javascript
Vue中引入样式文件的方法
Aug 18 Javascript
Vue网页html转换PDF(最低兼容ie10)的思路详解
Aug 24 Javascript
BootStrap模态框闪退问题实例代码详解
Dec 10 Javascript
图文讲解vue的v-if使用方法
Feb 11 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
php中取得URL的根域名的代码
2011/03/23 PHP
php实现excel中rank函数功能的方法
2015/01/20 PHP
php实现粘贴截图并完成上传功能
2015/05/17 PHP
PHP中$GLOBALS['HTTP_RAW_POST_DATA']和$_POST的区别分析
2017/07/03 PHP
jquery中获取id值方法小结
2013/09/22 Javascript
Windows8下搭建Node.js开发环境教程
2014/09/03 Javascript
js实现鼠标感应向下滑动隐藏菜单的方法
2015/02/20 Javascript
jquery获取多个checkbox的值异步提交给php
2015/07/07 Javascript
Jquery 分页插件之Jquery Pagination
2015/08/25 Javascript
JavaScript实现输入框(密码框)出现提示语
2016/01/12 Javascript
jquery自定义右键菜单、全选、不连续选择
2016/03/01 Javascript
React实现双向绑定示例代码
2016/09/19 Javascript
js中数组插入、删除元素操作的方法
2017/02/15 Javascript
Hexo已经看腻了,来手把手教你使用VuePress搭建个人博客
2018/04/26 Javascript
Intellij IDEA搭建vue-cli项目的方法步骤
2018/10/20 Javascript
原生JS实现动态添加新元素、删除元素方法
2019/05/05 Javascript
解决vue语法会有延迟加载显现{{xxx}}的问题
2019/11/14 Javascript
前端开发之便利店收银系统代码
2019/12/27 Javascript
django反向解析和正向解析的方式
2018/06/05 Python
python打包生成的exe文件运行时提示缺少模块的解决方法
2018/10/31 Python
CentOS下Python3的安装及创建虚拟环境的方法
2018/11/28 Python
用sqlalchemy构建Django连接池的实例
2019/08/29 Python
python脚本后台执行方式
2019/12/21 Python
python3读取csv文件任意行列代码实例
2020/01/13 Python
Django 删除upload_to文件的步骤
2020/03/30 Python
python_matplotlib改变横坐标和纵坐标上的刻度(ticks)方式
2020/05/16 Python
Python类及获取对象属性方法解析
2020/06/15 Python
django 装饰器 检测登录状态操作
2020/07/02 Python
用Python 执行cmd命令
2020/12/18 Python
html5+css如何实现中间大两头小的轮播效果
2018/12/06 HTML / CSS
UGG英国官方网站:UGG UK
2018/02/08 全球购物
社团文化节邀请函
2014/01/10 职场文书
驾驶员安全责任书
2014/07/22 职场文书
升学宴家长答谢词
2015/09/29 职场文书
MySQL CHAR和VARCHAR该如何选择
2021/05/31 MySQL
全新239军机修复记
2022/04/05 无线电