HTML 里 Node 和 Element 有什么区别?

发布:elantion 日期:2019-12-27 阅读:84 评论:0

我们在查找元素时经常会用到 getElementById 或者 getElementsByClassName,平时使用不会有什么问题,要么返回空,要么返回预期想要找的元素。但在 TypeScript 中,这二者的返回是不一样的,getElementById 返回的是 Element,而 getElementsByClassName 返回的是 HTMLCollection,这个 HTMLCollection 就有点特别了,它是一个类似数组的集合,里面保存的是 Node 列表。

Element 是 Node 的实现

Node可以称之为节点,而 Element 可以称之为元素,ElementNode 的子类,Node 包含除 Element 之外的很多东西,例如:文本节点、评论节点、DocumentDocumentFragment 等等,当然也包含 Element。这里举个例子,大家就很容易懂了:当我们想判断获取到的元素是不是 script 标签,看下面错误示范:

const nodes = document.getElementsByClassName('text');
const node = nodes[0];
if (!node) {
  return;
}
// 这里不能这么写
// node 不一定是 element,可能没有 tagName属性
const tagName = node.tagName;
// ...

保证是 Element 的写法

DOM 并没有转换 NodeElement 的方法,但可以利用 if 来确定是 Element,所以上面的错误代码应该改为这样:

// 省略前面部分代码

// 跳出非 ELement 实例
if (!(node instanceof Element)) {
    return;
}
// 这里就可以确定 node 就是 Element 实例了
const element = node as Element;
// 可以正常获取 tagName
const tagName = element.tagName.toUpperCase();
if (tagName !== 'SCRIPT') {
  return;
}
// 这里就可以 100% 确定 node 是 script 标签了
const scriptEl = element as HTMLScriptElement;
// do the rest of work

总结

以前习惯写JavaScript时不去判断元素是什么实例,也不会出现什么错误,因为按照目前html的习惯写法,极少出现查找到非 Element 的情况,于是就省去了那些判断条件。但写健壮的代码永远是更好的实践,希望大家在写 TypeScript 时能注意这个小细节哦。