自定义元素onclick事件触发异常:点击边界外仍响应的原因咨询
问题原因与解决办法
嘿,这个问题我之前也碰到过,核心原因出在自定义元素的默认布局行为上:
- 自定义元素(比如你写的
<my-test>)默认的 CSSdisplay属性是inline,而在表格单元格(<td>)里,inline 元素会被自动拉伸以填满整个单元格的可用宽度——哪怕你给 shadow DOM 里的 div 设置了200px的宽度,自定义元素本身还是会占据整个单元格的空间。 - 你把点击事件绑定在了自定义元素本身(
this.addEventListener),所以哪怕你点击的是单元格内视觉上“超出 div 范围”的区域,本质上还是点在了<my-test>元素上,自然会触发点击事件。
两种快速解决方法
方法一:在构造函数里直接设置自定义元素的样式
给自定义元素本身加上display和width样式,让它的尺寸由自己控制,而不是被表格单元格拉伸:
class Test extends HTMLElement { constructor() { super(); // 关键:给自定义元素本身设置布局样式 this.style.display = 'inline-block'; // 用 block 也可以,看你需要的布局效果 this.style.width = '200px'; var shadow = this.attachShadow( { mode: 'open' } ); var f = document.createElement('font'); f.innerHTML = 'text'; var div = document.createElement('div'); div.style.border = '1px solid black'; div.style.width = '200px'; this.addEventListener('click', function() { console.log('clicked'); }); div.appendChild(f); shadow.appendChild(div); } } customElements.define('my-test', Test);
方法二:用全局 CSS 统一设置
如果不想在 JS 里写样式,也可以在页面的 CSS 中直接定义自定义元素的样式,这样更灵活:
my-test { display: inline-block; width: 200px; }
这样修改后,<my-test>就只会占据 200px 的宽度,不会填满整个表格单元格了,点击单元格内元素外的区域就不会触发点击事件啦。
补充一句:表格单元格的布局规则比较特殊,inline 元素在里面会自动填充宽度,把自定义元素改成inline-block或者block后,它的尺寸就由自身的 width 属性决定,不会被单元格强制拉伸了。
内容的提问来源于stack exchange,提问作者Andreas
相关产品推荐
相关产品推荐

