IE11中通过React DOM ref调用element.contains提示未定义的问题
解决IE11中React DOM ref调用contains报错的问题
这个问题我之前帮同事排查过,确实挺坑的——明明MDN说IE支持contains方法,结果在React里调用就报“contains未定义”,大概率是ref的使用方式不对导致的,不是IE的锅😅
最常见的原因:误用React.createRef()的返回值
如果你在组件里用了React 16.3+的createRef()来定义ref,比如:
constructor(props) { super(props); this.list = React.createRef(); // 这里返回的是一个ref对象,不是DOM元素! }
那直接调用this.list.contains(e.target)肯定会报错——因为this.list是React的ref包装对象,真实的DOM元素存在于它的current属性里。正确的写法应该是:
if (this.list.current && this.list.current.contains(e.target)) { // 你的业务逻辑 }
IE11对这类属性访问的错误会直接抛出,而现代浏览器可能因为某些兼容处理没触发,但本质上写法是错误的。
其他可能的ref使用问题
- 如果你用的是回调ref(比如
<ul ref={el => this.list = el}>):
这种写法是直接把DOM元素赋值给this.list,理论上没问题,但要注意IE11的事件模型里,e.target可能会指向文本节点(而不是你预期的元素节点),这时候可以先判断e.target.nodeType === 1确认是元素节点后再调用contains。 - 如果你还在使用旧的字符串ref(不推荐):
比如<ul ref="list">,那你需要用this.refs.list.contains(e.target),而不是this.list——this.list本身是undefined,自然会报错。
额外的小提醒
- 记得在事件监听里确保this的指向正确:用箭头函数比
bind(this)更稳妥,比如:
componentDidMount() { window.addEventListener('mousedown', (e) => { // 这里的this自动绑定组件实例,不用额外bind if (this.list.current && this.list.current.contains(e.target)) { // 逻辑代码 } }); }
- 加个存在性判断:避免组件卸载后或者DOM还没挂载时调用
contains,用this.list.current && ...(IE11不支持可选链操作符?.,所以要兼容的话别用)。
内容的提问来源于stack exchange,提问作者fraxture
相关产品推荐
相关产品推荐

