我想遍历相当复杂的结构
第一次尝试
var textFromCLick = $0.closest('span').parentElement.querySelector('label').innerText
这只在用户点击具有相同结构的元素时起作用。
如果结构不同,我得到'无法读取属性'querySelector'的null'
所以我想出了这个肮脏的代码
if(0$.closest('span') !== null) {
var el2 = 0$.closest('span');
if (el2.parentElement.querySelector('label') !== null) {
textFromCLick = el2.parentElement.querySelector('label').innerText;
} else {
textFromCLick = "";
}
} else {
textFromCLick = "";
}
这个工作但是…如您所见,代码太长且效率低下。我怎样才能使它优雅呢?
如果任何调用都可能失败,则链接方法调用是脆弱的,如
$0.closest('span').parentElement.querySelector('label').innerText;
如果任何部分失败,下一部分可能会抛出错误。因此,在每个部分可能返回一个值从而导致下一个部分抛出错误的点上测试每个部分。在这种情况下,各种表达式可能返回null或其他值,因此要测试每个位:
let span = $0.closest('span');
let parent = span && span.parent;
let label = parent && parent.querySelector('label');
let text = label? label.textContent : '';
您可以将第二行和第三行合并为:
let label = span && span.parent.querySelector('label');
的基础是,如果有一个span(或任何低于根HTML元素的元素),它将有一个父节点,因此span.parent
不太可能失败。
let text = '';
try {
text = $0.closest('span').parentElement.querySelector('label').textContent;
catch (e) {
text = '';
}
一个更好的策略是通过一些属性(如id或class)来关联元素,这样关系就不是结构化的,例如
function findLabel() {
let label = document.querySelector('label.' + this.className);
console.log(label && label.textContent);
}
window.onload = ()=>{
document.querySelectorAll('button').forEach(button =>
button.addEventListener('click', findLabel)
);
}
<p>
<span>
<button class="fooBar0">Find my label</button>
</span>
</p>
<label class="fooBar0">Here I am</label>