继承HTMLDivElement创建自定义类后调用新增方法报错如何解决
你遇到的报错是因为继承原生内置元素的自定义类需要完成浏览器注册逻辑,且使用时要显式声明关联,普通<div>默认返回的依然是原生HTMLDivElement实例,自然没有你定义的scrollHorizontal方法。
解决方案
方案1:使用自定义内置元素(标准实现)
这是Web Components标准中推荐的内置元素扩展方式,完全符合你的需求,不会污染原生原型。
- 首先完成自定义元素注册
export class ScrollableElement extends HTMLDivElement { scrollHorizontal(left: number) { this.scrollTo({ left, behavior: 'smooth' }); } } // 注册自定义元素,必须指定extends参数关联div标签 customElements.define('scrollable-div', ScrollableElement, { extends: 'div' });
- 使用时给div添加
is属性绑定自定义元素
原生HTML写法:
<div is="scrollable-div" id="scroll-container"></div>
框架中写法(React/Vue都支持):
// React <div is="scrollable-div" ref={listRef}></div> // Vue3 <div is="scrollable-div" ref="listRef"></div>
此时ref拿到的就是ScrollableElement实例,可以直接调用scrollHorizontal方法。如果需要兼容低版本Safari,引入自定义元素polyfill即可。
方案2:组合封装(无兼容问题,实现更简单)
如果不想处理自定义元素的注册和兼容问题,可以用组合的方式封装原生DOM,没有任何使用限制:
export class ScrollableElement { constructor(private nativeElement: HTMLDivElement) {} scrollHorizontal(left: number) { this.nativeElement.scrollTo({ left, behavior: 'smooth' }); } // 可按需透出原生DOM的属性和方法 get scrollLeft() { return this.nativeElement.scrollLeft; } get clientWidth() { return this.nativeElement.clientWidth; } }
使用时先拿到原生div的ref,再实例化封装类即可:
// 示例:Vue3中使用 const listRef = ref<HTMLDivElement | null>(null); const scrollable = computed(() => listRef.value ? new ScrollableElement(listRef.value) : null ); // 调用方法 scrollable.value?.scrollHorizontal(200);
方案3:Proxy代理(无侵入,用法和原生DOM一致)
如果希望在不改动现有代码结构的前提下扩展方法,可以用Proxy代理原生DOM实例:
function createScrollableElement(el: HTMLDivElement) { return new Proxy(el, { get(target, prop) { if (prop === 'scrollHorizontal') { return (left: number) => target.scrollTo({ left, behavior: 'smooth' }); } return Reflect.get(target, prop, target); } }) }
使用方式:
const listEl = document.getElementById('scroll-container') as HTMLDivElement; const scrollableEl = createScrollableElement(listEl); scrollableEl.scrollHorizontal(200); // 原生方法也可以正常调用 console.log(scrollableEl.scrollLeft);
内容的提问来源于stack exchange,提问作者zilijonas
相关产品推荐
相关产品推荐

