We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
在项目里,我们经常会使用组件库进行快速开发,然而在过程中,又难免会遇到对组件库的改造和拓展,如何优雅且简单的进行重构,下面让我们从一个简单需求来探索组件的奇技淫巧--Mixins和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> 复制代码
从源码里可以得到以下信息
再看看我们的需求 实现所有页面按钮的点击事件节流控制,这里有几个关键点
实现所有页面按钮的点击事件节流控制
那么需求的难点就在于,如何实现点击事件的劫持?在这里有两种方案
Mixins 在官方Vue文档中已经有了很详细的介绍,不熟悉的朋友们可以看看,用一句话来理解,即合并组件的组件
官方介绍
用一张图来表示
直接上源码
// 节流函数 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) } } } 复制代码
// 节流函数 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) } } }
复制代码
mixins的原理很容易理解,上列源码我们做了这些操作,来实现合并ivew Button组件,劫持click事件
使用mixins 来实现我们需求很简单,但也因此会有许多问题
所谓高阶组件其实就是高阶函数,React 和 Vue 都证明了一件事儿:一个函数就是一个组件。所以组件是函数这个命题成立了,那高阶组件很自然的就是高阶函数,即一个返回函数的函数
HOC的详细介绍和实现,这篇文章探索Vue高阶组件有详细介绍,用一句话来理解,即包裹组件的组件
// 节流函数 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) } } 复制代码
// 节流函数 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) } }
HOC的特点在于它的包裹性,上列源码我们做了这些操作,来实现包裹iview的Button组件,劫持click事件
HOC的包裹性同时也会带来几个问题
Mixins 和 HOC 都能实现这个简单的需求,希望大家能理解这两种技巧,解决项目中的问题
源码:github.com/warpcgd/mix…
demo:warpcgd.github.io/mixinAndHoc…
The text was updated successfully, but these errors were encountered:
No branches or pull requests
项目中使用组件库遇到的需求
需求: 实现所有页面按钮的点击事件节流控制
随便选用一套组件库,在这次例子里,我选用iview进行开发
iview官网的Button组件的使用方法如下
Button的源码也很简单,在这里我剔除了不相关的内容
从源码里可以得到以下信息
需求怎么实现
再看看我们的需求
实现所有页面按钮的点击事件节流控制
,这里有几个关键点那么需求的难点就在于,如何实现点击事件的劫持?在这里有两种方案
Mixins
1. Mixin是什么
Mixins 在官方Vue文档中已经有了很详细的介绍,不熟悉的朋友们可以看看,用一句话来理解,即合并组件的组件
官方介绍
用一张图来表示
2. 怎么解决需求
直接上源码
3. 原理
mixins的原理很容易理解,上列源码我们做了这些操作,来实现合并ivew Button组件,劫持click事件
使用mixins 来实现我们需求很简单,但也因此会有许多问题
那么有没有更好的方法?
HOC
1.什么是HOC?
HOC的详细介绍和实现,这篇文章探索Vue高阶组件有详细介绍,用一句话来理解,即包裹组件的组件
用一张图来表示
2. 怎么解决需求
直接上源码
3. 原理
HOC的特点在于它的包裹性,上列源码我们做了这些操作,来实现包裹iview的Button组件,劫持click事件
HOC的包裹性同时也会带来几个问题
总结
Mixins 和 HOC 都能实现这个简单的需求,希望大家能理解这两种技巧,解决项目中的问题
源码:github.com/warpcgd/mix…
demo:warpcgd.github.io/mixinAndHoc…
The text was updated successfully, but these errors were encountered: