WebView注入JS点击元素时如何仅选子元素,避免父元素同时被选中
问题原因
当前实现为DOM内所有元素都绑定了点击事件监听器,浏览器默认的事件冒泡机制会导致子元素触发的点击事件向上传递到所有父级元素,触发父元素绑定的点击回调,因此出现父子元素同时被选中的问题。
解决方案
只需修改注入的JavaScript代码,在点击事件回调中阻止事件冒泡即可,修改后的完整JS代码如下:
var lastSelectedItem = null; var showHighlighted = function(/* HTML element */view, /*boolean */highlighted) { if (view) { view.style.cssText = highlighted? 'background-color: #ADD8E6; ' :' '; } }; Object.prototype.each = function (fn, bind) { for (var i = 0; i < this.length; i++) { if (i in this) { fn.call(bind, this[i], i, this); } } }; var _addListener = document.addEventListener || document.attachEvent, _eventClick = window.addEventListener ? 'click' : 'onclick'; var elements = document.body.getElementsByTagName('*'); elements.each(function (el) { _addListener.call(el, _eventClick, function (e) { // 阻止事件向上冒泡,避免父元素点击事件被触发 e = e || window.event; if (e.stopPropagation) { e.stopPropagation(); } else { e.cancelBubble = true; } // 原有逻辑保持不变 showHighlighted(lastSelectedItem, false); lastSelectedItem = el; showHighlighted(lastSelectedItem, true); appHost.onClick(el.outerHTML.replace(el.innerHTML , ' ')); }, false); });
可选优化方案
如果不需要给所有元素单独绑定事件,也可以直接在document层面绑定单个点击事件,通过e.target直接获取实际点击的最内层元素,代码更简洁、性能更好:
var lastSelectedItem = null; var showHighlighted = function(view, highlighted) { if (view) view.style.cssText = highlighted? 'background-color: #ADD8E6; ' :' '; }; document.addEventListener('click', function(e) { var target = e.target; showHighlighted(lastSelectedItem, false); lastSelectedItem = target; showHighlighted(lastSelectedItem, true); appHost.onClick(target.outerHTML.replace(target.innerHTML , ' ')); }, false);
内容的提问来源于stack exchange,提问作者Android Tutorial's
相关产品推荐
相关产品推荐

