在项目里,我们经常会使用组件库进行快速开发,然而在过程中,又难免会遇到对组件库的改造和拓展,如何优雅且简单的进行重构,下面让我们从一个简单需求来探索组件的奇技淫巧--Mixins和HOC

项目中使用组件库遇到的需求

需求: 实现所有页面按钮的点击事件节流控制


奇技淫巧 - Vue Mixins 高级组件 与 Vue HOC 高阶组件 实践

随便选用一套组件库,在这次例子里,我选用iview进行开发

iview官网的Button组件的使用方法如下

<template> <Button @click="click">Default</Button> </template> <script> export default { methods: { click () { console.log('yes') } } } </script> 复制代码

Button的 源码 也很简单,在这里我剔除了不相关的内容

<template> <button @click="handleClick"></button> </template> <script> export default { name: 'Button', components: { Icon }, props: { }, data () { }, computed: { }, methods: { handleClick (event) { this.$emit('click', event); } }, mounted () { } }; </script> 复制代码

从源码里可以得到以下信息

iview的Button组件封装了原生的button组件 对原生的button组件,进行了click事件的绑定 click事件触发时,向组件emit了click事件 需求怎么实现

再看看我们的需求 实现所有页面按钮的点击事件节流控制 ,这里有几个关键点

点击事件,iview的Button组件里已经对原生的button的click进行了绑定,我们需要劫持这段绑定,进行节流 节流控制,节流(debounce)函数,网上有很多示例,容易实现

那么需求的难点就在于,如何实现点击事件的劫持?在这里有两种方案

Mixins 1. Mixin是什么

Mixins 在官方Vue文档中已经有了很详细的介绍,不熟悉的朋友们可以看看,用一句话来理解,即合并组件的组件

官方介绍

用一张图来表示


奇技淫巧 - Vue Mixins 高级组件 与 Vue HOC 高阶组件 实践
2. 怎么解决需求

直接上源码

// 节流函数 function debounce (func, delay, context, event) { clearTimeout(func.timer) func.timer = setTimeout(function () { func.call(context, event) }, delay) } // iview中click方法拷贝 function _handleClick (event) { this.$emit('click', event) const openInNewWindow = event.ctrlKey || event.metaKey this.handleCheckClick(event, openInNewWindow) } // 导出新组件 export default { props: { }, mixins: [Vue.options.components.Button], // iview 中Button组件 data () { return {} }, mounted () { console.log('mixins succeed') }, methods: { handleClick (event) { let that = this console.log('debounce') debounce(_handleClickLink, 300, that, event) } } } 复制代码 3. 原理

mixins的原理很容易理解,上列源码我们做了这些操作,来实现合并ivew Button组件,劫持click事件

创建debounce节流函数 复制iview Button组件中handleClick方法为_handleClick 导出对象,methods里重写handleClick方法,进行节流控制

使用mixins 来实现我们需求很简单,但也因此会有许多问题

需要知道Button源码结构 带来了隐式依赖,如果mixins嵌套,会很难理解 那么有没有更好的方法? HOC 1.什么是HOC?

所谓高阶组件其实就是高阶函数,React 和 Vue 都证明了一件事儿:一个函数就是一个组件。所以组件是函数这个命题成立了,那高阶组件很自然的就是高阶函数,即一个返回函数的函数

HOC的详细介绍和实现,这篇文章探索Vue高阶组件有详细介绍,用一句话来理解,即包裹组件的组件

用一张图来表示


奇技淫巧 - Vue Mixins 高级组件 与 Vue HOC 高阶组件 实践
2. 怎么解决需求

直接上源码

// 节流函数 function debounce (func, delay, context, event) { clearTimeout(func.timer) func.timer = setTimeout(function () { func.call(context, event) }, delay) } // 导出新组件 export default { props: {}, name: 'ButtonHoc', data () { return {} }, mounted () { console.log('HOC succeed') }, methods: { handleClickLink (event) { let that = this console.log('debounce') // that.$listeners.click为绑定在新组件上的click函数 debounce(that.$listeners.click, 300, that, event) } }, render (h) { const slots = Object.keys(this.$slots) .reduce((arr, key) => arr.concat(this.$slots[key]), []) .map(vnode => { vnode.context = this._self return vnode }) return h('Button', { on: { click: this.handleClickLink //新组件绑定click事件 }, props: this.$props, // 透传 scopedSlots scopedSlots: this.$scopedSlots, attrs: this.$attrs }, slots) } } 复制代码 3. 原理

HOC的特点在于它的包裹性,上列源码我们做了这些操作,来实现包裹iview的Button组件,劫持click事件

创建debounce节流函数 导出新的组件 render渲染出iview Button Button 绑定debounce后的click方法

HOC的包裹性同时也会带来几个问题

组件之间通信会被拦截,比如子组件访问父组件的方法(this.$parent.methods) vue官方并没有推荐使用HOC :(

本文前端(javascript)相关术语:javascript是什么意思 javascript下载 javascript权威指南 javascript基础教程 javascript 正则表达式 javascript设计模式 javascript高级程序设计 精通javascript javascript教程

代码区博客精选文章
分页:12
转载请注明
本文标题:奇技淫巧 - Vue Mixins 高级组件 与 Vue HOC 高阶组件 实践
本站链接:https://www.codesec.net/view/628140.html


1.凡CodeSecTeam转载的文章,均出自其它媒体或其他官网介绍,目的在于传递更多的信息,并不代表本站赞同其观点和其真实性负责;
2.转载的文章仅代表原创作者观点,与本站无关。其原创性以及文中陈述文字和内容未经本站证实,本站对该文以及其中全部或者部分内容、文字的真实性、完整性、及时性,不作出任何保证或承若;
3.如本站转载稿涉及版权等问题,请作者及时联系本站,我们会及时处理。
登录后可拥有收藏文章、关注作者等权限...
技术大类 技术大类 | 前端(javascript) | 评论(0) | 阅读(128)