前言
❝随着技术的快速发展,前端为了快速开发,我们一般会接入像elementui这样的库,以element为例,一些组件无法满足我们的需求,就需要做二次封装。今天想着尝试利用vue的函数式组件做一下二次封装。
先来看一个最简单的demo来补充点基础知识
// demo.vue
"demo">"debounce" maxlength='5' @blur="inputBlur"/>
我们再来尝试封装一个elementui的el-button组件
// debounce.js 关键代码
if (vNode.componentOptions && vNode.componentOptions.tag === 'el-button') {
const funDefault = vNode.componentOptions.listeners && vNode.componentOptions.listeners.click
if (!funDefault) {
console.warn('请传入click方法(@click)')
return null
}
const fun = debounce(funDefault, time, Switch)
vNode.componentOptions.listeners.click = fun
}
❝我们elementui的组件和原生标签的区别是需要通过vNode.componentOptions获取,接下来贴出完整的代码
const debounce = (fn, delay=500, Switch=true) => {
let timeout = null;
return (params) => {
clearTimeout(timeout)
if (!Switch) {
return fn(params)
}
timeout = window.setTimeout(() => {
// el-button获取到的是数组,input获取到的是function
if (!Array.isArray(fn)) {
fn = [fn]
}
fn[0](params)
}, 1000)
}
}
export default {
functional: true,
render: function(createElement, context) {
const vNodeLists = context.slots().default
const time = context.props.time
const Switch = context.props.Switch
if (!vNodeLists) {
console.warn('必须要有一个子元素')
return null
}
const vNode = vNodeLists[0] || {}
if (vNode.componentOptions && vNode.componentOptions.tag === 'el-button') {
const funDefault = vNode.componentOptions.listeners && vNode.componentOptions.listeners.click
if (!funDefault) {
console.warn('请传入click方法(@click)')
return null
}
const fun = debounce(funDefault, time, Switch)
vNode.componentOptions.listeners.click = fun
} else if (vNode.tag && vNode.tag === 'input') {
const funDefault = vNode.data.on && vNode.data.on.input
if (!funDefault) {
console.warn('请传入input方法(@input)')
return null
}
const fun = debounce(funDefault, time, Switch)
vNode.data.on.input = fun
} else {
console.warn('仅支持input和el-button')
return null
}
return vNode
}
}