项目中经常要使用 element-ui 这些原生组件进行二次封装,但是封装后的组件如果要调用原生组件的 method 只能通过 refs 去调用,使用上多了一层,于是我封装了一个函数实现了对原生组件 method 的继承。
工具方法
原理:通过遍历原生组件的函数属性,在当前封装后的组件上添加一个
function,通过call绑定原生组件作为上下文从而实现method继承
/**
* 继承组件的原生方法
*
* @export
* @param {*} target 目标组件,即当前封装后的组件
* @param {*} source 原生组件
* @param {string[]} [pickMethods] 只选择指定的函数,如果为空则默认继承全部
*/
export function inheritMethods(target: any, source: any, pickMethods?: string[]) {
// console.log('inheritMethods', target, source)
if (!target || !source) {
return
}
if (!pickMethods) {
pickMethods = Object.keys(source).filter(key =>
key.length > 3 &&
!key.startsWith('$') &&
!key.startsWith('_') &&
!target[key] &&
typeof source[key] === "function")
}
for (const method of pickMethods) {
if (target[method]) {
continue
}
target[method] = function (...ars: any) {
return source[method].call(source, ...ars)
}
}
}
使用方法
在封装后的组件 mounted 钩子上调用 inheritMethods 完成方法继承后,其他地方使用封装后的组件就可以像原生组件一样直接调用了
- 使用
inheritMethods前:this.$refs.customInput.$refs.elInput.focus() - 使用
inheritMethods后:this.$refs.customInput.focus()
<template>
<el-input ref="elInput" v-bind="$attrs" v-on="$listeners"></el-input>
</template>
<script>
import { inheritMethods } from '@/utils"
extend default {
mounted() {
inheritMethods(this, this.$refs.elInput)
}
}
</script>