You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在TypeScript中实现DOM元素扩展类 支持原生与自定义方法直接调用

TypeScript DOM元素扩展类实现方案

要实现自定义方法和原生DOM方法统一调用,需要同时处理类型声明和运行时转发两部分:类型层面让扩展类兼容原生DOM元素的所有类型定义,运行时把原生属性/方法的调用转发到内部持有的DOM元素上即可,完整实现如下:

// 类型合并:让FormElement<T>继承原生元素的所有类型定义,保证TS类型检查正常
export interface FormElement<T extends HTMLElement = HTMLElement> extends T {}

export class FormElement<T extends HTMLElement = HTMLElement> {
  public element: T;

  constructor(selector: string) {
    const el = document.querySelector<T>(selector);
    if (!el) throw new Error(`找不到对应元素,选择器:${selector}`);
    this.element = el;

    // 运行时代理:把不在当前类的属性/方法调用转发到原生DOM元素
    return new Proxy(this, {
      get(target, prop) {
        // 优先读取扩展类自身的属性/方法
        if (prop in target) {
          return Reflect.get(target, prop);
        }
        // 读取原生元素的属性/方法
        const originProp = Reflect.get(target.element, prop);
        // 原生方法需要绑定this到DOM元素,避免调用报错
        if (typeof originProp === 'function') {
          return originProp.bind(target.element);
        }
        return originProp;
      },
      set(target, prop, value) {
        // 赋值逻辑同理,优先给扩展类自身,否则赋值给原生元素
        if (prop in target) {
          return Reflect.set(target, prop, value);
        }
        return Reflect.set(target.element, prop, value);
      }
    });
  }

  public disable(): void {
    this.element.setAttribute('disabled', 'disabled');
  }

  public enable(): void {
    this.element.removeAttribute('disabled');
  }
}

使用示例

和你期望的调用方式完全一致,自定义方法和原生方法/属性都可以直接调用:

class SomeComponent {
  private get nameInput(): FormElement<HTMLInputElement> {
    return new FormElement('input#company_msisdn')
  }  

  private disableNameInput = (): void => {
    // 调用自定义扩展方法
    this.nameInput.disable()
  }

  private initializeNameInput = (): void => {
    // 直接调用原生DOM方法
    this.nameInput.addEventListener('change', this.onNameInputChange)
    // 直接访问原生DOM属性
    console.log(this.nameInput.value)
  }

  private onNameInputChange = (e: Event) => {
    // 业务逻辑
  }
}

补充说明

  • 该实现不会污染全局HTMLElement原型,仅在显式使用FormElement的场景生效,无全局副作用
  • 内置了元素空校验,找不到对应元素时会提前抛出错误,避免后续空指针异常
  • 如果需要支持属性删除、遍历等更复杂的操作,可按需补充Proxy的对应拦截方法

内容的提问来源于stack exchange,提问作者Sergio Belevskij

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 15:06:03