VueMixins高级组件与VueHOC高阶组件

14207565-3f9d85d584f810c1

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

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

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

14207565-8958815b6a6d02d1

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

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

Default

exportdefault{

methods: {

click () {

console.log('yes')

}

}

}

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

exportdefault{

name:'Button',

components: { Icon },

props: {

},

data () {

},

computed: {

},

methods: {

handleClick (event) {

this.$emit('click', event);

}

},

mounted () {

}

};

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

1.iview的Button组件封装了原生的button组件

2.对原生的button组件,进行了click事件的绑定

3.click事件触发时,向组件emit了click事件

需求怎么实现

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

1.点击事件,iview的Button组件里已经对原生的button的click进行了绑定,我们需要劫持这段绑定,进行节流

2.节流控制,节流(debounce)函数,网上有很多示例,容易实现

顺便给大家推荐一个裙,它的前面是 537,中间是631,最后就是 707。想要学习前端的小伙伴可以加入我们一起学习,互相帮助。群里每天晚上都有大神免费直播上课,如果不是想学习的小伙伴就不要加啦。(537-631-707)

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

14207565-664ea0dd1e01bdc2

Mixins

 1. Mixin是什么?  

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

官方介绍:https://cn.vuejs.org/v2/guide/mixins.html

用一张图来表示:

14207565-9293232690f8fce5

 2. 怎么解决需求?  

// 节流函数

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

constopenInNewWindow = event.ctrlKey || event.metaKey

this.handleCheckClick(event, openInNewWindow)

}

// 导出新组件

exportdefault{

props: {

},

mixins: [Vue.options.components.Button],// iview 中Button组件

data () {

return{}

},

mounted () {

console.log('mixins succeed')

},

methods: {

handleClick (event) {

letthat =this

console.log('debounce')

debounce(_handleClickLink,300, that, event)

}

}

}

 3. 原理  

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

1.创建debounce节流函数

2.复制iview Button组件中handleClick方法为_handleClick

3.导出对象,methods里重写handleClick方法,进行节流控制

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

1.需要知道Button源码结构

2.带来了隐式依赖,如果mixins嵌套,会很难理解

HOC

 1.什么是HOC?  

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

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

用一张图来表示:

14207565-6e66ca9f6fa4b41f

 2. 怎么解决需求?  

直接上源码:

// 节流函数

functiondebounce(func, delay, context, event){

clearTimeout(func.timer)

func.timer = setTimeout(function(){

func.call(context, event)

}, delay)

}

// 导出新组件

exportdefault{

props: {},

name:'ButtonHoc',

data () {

return{}

},

mounted () {

console.log('HOC succeed')

},

methods: {

handleClickLink (event) {

letthat =this

console.log('debounce')

// that.$listeners.click为绑定在新组件上的click函数

debounce(that.$listeners.click,300, that, event)

}

},

render (h) {

constslots =Object.keys(this.$slots)

.reduce((arr, key) =>arr.concat(this.$slots[key]), [])

.map(vnode=>{

vnode.context =this._self

returnvnode

})

returnh('Button', {

on: {

click:this.handleClickLink//新组件绑定click事件

},

props:this.$props,

// 透传 scopedSlots

scopedSlots:this.$scopedSlots,

attrs:this.$attrs

}, slots)

}

}

 3. 原理  

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

1.创建debounce节流函数

2.导出新的组件

3.render渲染出iview Button

4.Button 绑定debounce后的click方法

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

1.组件之间通信会被拦截,比如子组件访问父组件的方法(this.$parent.methods)

2.vue官方并没有推荐使用HOC :(

总结

Mixins 和 HOC 都能实现这个简单的需求,希望大家能理解这两种技巧,解决项目中的问题。

源码:https://github.com/warpcgd/mixinAndHoc

demo:https://warpcgd.github.io/mixinAndHoc/#/

Button:https://www.iviewui.com/components/button

Button源码:https://github.com/iview/iview/blob/3.x/src/components/button/button.vue

探索Vue高阶组件:http://hcysun.me/vue-design/more/vue-hoc.html

*  作者:warpcgd

*  原标题:奇技淫巧 - Vue Mixins 高级组件 与 Vue HOC 高阶组件 实践

*  原文地址:https://segmentfault.com/a/1190000017745603

*  声明:转载文章和图片均来自公开网络,版权归作者本人所有。如果出处有误或侵犯到原作者权益,请与我们联系删除或授权事宜。

猜你喜欢

转载自blog.csdn.net/weixin_33756418/article/details/90991772
今日推荐