一个函数实现组件 method 继承

5 阅读1分钟

项目中经常要使用 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>