FrankKai / FrankKai.github.io

FE blog
https://frankkai.github.io/
362 stars 39 forks source link

DOM进阶之Node #189

Open FrankKai opened 4 years ago

FrankKai commented 4 years ago

Node interface概览

Node Properties

Node Methods

...

基本都是一些增删盖查节点的操作。

常见疑问

var pTag = document.createElement('p');
var spanTag = document.createElement('span');
var str = "foo bar baz";

pTag.appendChild(spanTag);// <p><span></span></p>
pTag.appendChild(str);// Uncaught TypeError: Failed to execute 'appendChild' on 'Node': parameter 1 is not of type 'Node'.

pTag.append(spanTag);// <p><span></span></p>
pTag.append(str);// <p>foo bar baz</p>
pTag.append(spanTag, str);// NodeList [<span>, #text "foo bar baz"]

Node.textContent,Node.nodeValue区别是什么

Node.nodeValue一般都为null。 Node.textContent是当前节点的所有子节点的文本内容,iframe内的标签也会以DOMString的形式出现。

Node.textContent,Node.innerText的区别是什么?

Node.textContent,Node.innerText的区别是什么?

Node.innerText代表渲染过的当前节点和它的子孙节点的文本内容。style标签会生效,标签属性会生效。 textContent则是未渲染的,比如说style,带属性的普通标签会被忽略,直接取全部的文本节点。

<li id="foo">
    文本内容
    <span style="display:none">噢噢</span>
</li>
const domFoo = document.getElementById("foo");
domFoo.innerText; // 文本内容
domFoo.textContent; // 文本内容噢噢

Node.textContent, Node.innerHTML的区别是什么?

textContent返回的是raw数据。 innerHTML返回的是HTML entites。

比如说如果<div><span>的文本子节包含&,>,<,textContent会正常返回,而innerHTML则返回”&amp“,”&lt“,”&gt;“。

Node.innerText,Node.outerText的区别是什么?

Node.innerText,Node.outerText的区别是什么?

Node.innerText代表的是渲染过的当前节点和它的子孙节点的文本内容。

stackoverflow上有一个很好的例子可以说明:What is the difference between innerText and outerText? innerText changes only text within HTML tags, e.g.

<div>
  <p>Change Me</p>
</div>

p.innerText = "Changed!"

Becomes

<div>
  <p>Changed!</p>
</div>

Whereas outerText:

<div>
  <p>Change Me</p>
</div>

p.outerText = "Changed!"

Becomes

<div>
   Changed! <!--可以看到这里的p标签已经被移除了,只留下了Changed!-->
</div>

虽然上面的例子说明了,Node.outerText的作用,但是还不够明显。

这样会更加明显:

<div>
  <p>Change Me</p>
</div>

div.innerText = "Changed!"

Becomes

<div>
  Changed!
</div>

Whereas outerText:

<div>
  <p>Change Me</p>
</div>

p.outerText = "Changed!"

Becomes

   Changed! <!--可以看到这里,不仅p标签已经被移除了,而且div标签也被移除了,只留下了Changed!-->

innerText的setter具有一定的破坏力,但是outerText的setter破坏力更大。 总而言之,在使用innerText和outerText的setter时,一定要谨慎要小心。

Node.innerHTML,Node.outerHTML的区别是什么?

举两个例子:

获取DOM字符串:

<div id="d">
  <p>Content</p>
  <p>Further Elaborated</p>
</div>
var d = document.getElementById("d");
console.log(d.outerHTML);

// The string '<div id="d"><p>Content</p><p>Further Elaborated</p></div>'
// is written to the console window

设置DOM字符串:

<div id="container">
  <div id="d">This is a div.</div>
</div>
var container = document.getElementById("container");
var d = document.getElementById("d");

console.log(container.firstChild.nodeName); // logs "DIV"

// 这一行非常非常有用,一定要牢记
d.outerHTML = "<p>This paragraph replaced the original div.</p>";

console.log(container.firstChild.nodeName); // logs "P"

// The #d div is no longer part of the document tree,
// the new paragraph replaced it.

Node.className,Node.classList的区别是什么?

// item的class名称
let el = document.getElementById('item');

if (el.className === 'active'){
  el.className = 'inactive';
} else {
  el.className = 'active';
}
const div = document.createElement('div');
div.className = 'foo';

// our starting state: <div class="foo"></div>
console.log(div.outerHTML);

// use the classList API to remove and add classes
div.classList.remove("foo");
div.classList.add("anotherclass");

// <div class="anotherclass"></div>
console.log(div.outerHTML);

// if visible is set remove it, otherwise add it
div.classList.toggle("visible");

// add/remove visible, depending on test conditional, i less than 10
div.classList.toggle("visible", i < 10 );

console.log(div.classList.contains("foo"));

// add or remove multiple classes
div.classList.add("foo", "bar", "baz");
div.classList.remove("foo", "bar", "baz");

// add or remove multiple classes using spread syntax
const cls = ["foo", "bar"];
div.classList.add(...cls); 
div.classList.remove(...cls);

// replace class "foo" with class "bar"
div.classList.replace("foo", "bar");

Node.offsetWidth,Node.scrollWidth,Node.clientWidth的区别是什么?

image

image

规范中的定义:

The offsetWidth attribute must return the result of running these steps: If the element does not have any associated CSS layout box return zero and terminate this algorithm. Return the border edge width of the first CSS layout box associated with the element, ignoring any transforms that apply to the element and its ancestors.

The scrollWidth attribute must return the result of running these steps: Let document be the element’s node document. If document is not the active document, return zero and terminate these steps. Let viewport width be the width of the viewport excluding the width of the scroll bar, if any, or zero if there is no viewport. If the element is the root element and document is not in quirks mode return max(viewport scrolling area width, viewport width). If the element is the HTML body element, document is in quirks mode and the element is not potentially scrollable, return max(viewport scrolling area width, viewport width). If the element does not have any associated CSS layout box return zero and terminate these steps. Return the width of the element’s scrolling area.

The clientWidth attribute must run these steps: If the element has no associated CSS layout box or if the CSS layout box is inline, return zero. If the element is the root element and the element’s node document is not in quirks mode, or if the element is the HTML body element and the element’s node document is in quirks mode, return the viewport width excluding the size of a rendered scroll bar (if any). Return the width of the padding edge excluding the width of any rendered scrollbar between the padding edge and the border edge, ignoring any transforms that apply to the element and its ancestors.

https://www.w3.org/TR/2016/WD-cssom-view-1-20160317/#dom-element-clientwidth

参考资料

https://developer.mozilla.org/en-US/docs/Web/API/Node https://developer.mozilla.org/en-US/docs/Web/API/ParentNode/append https://developer.mozilla.org/en-US/docs/Web/API/Node/appendChild https://developer.mozilla.org/en/docs/Web/API/Node/textContent https://developer.mozilla.org/en-US/docs/Web/API/Node/nodeValue https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/innerText https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/outerText https://developer.mozilla.org/en-US/docs/Web/API/Element/innerHTML https://developer.mozilla.org/en-US/docs/Web/API/Element/outerHTML https://developer.mozilla.org/en-US/docs/Web/API/Element/className https://developer.mozilla.org/en-US/docs/Web/API/Element/classList https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/offsetWidth https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollWidth https://developer.mozilla.org/en-US/docs/Web/API/Element/clientWidth