ホームページ  >  記事  >  ウェブフロントエンド  >  一般的な JavaScript ネイティブ DOM 操作 API の概要

一般的な JavaScript ネイティブ DOM 操作 API の概要

黄舟
黄舟オリジナル
2017-02-21 11:51:351138ブラウズ



最近のインタビュー中にこの質問に行き詰まったので、時間をかけて注意深く見直しました。

数種類のオブジェクト

Node

Node は、中国語でノードと呼ばれるインターフェイスであり、多くの種類の DOM 要素がそれを継承し、同じ基本プロパティとメソッドを共有します。共通ノードには、要素、テキスト、属性、コメント、ドキュメントなどが含まれます (ノードと要素の違いに注意してください。要素はノードの一種です)。

NodeはNodeの型を表すnodeType属性を持ち、その値は対応するNodeの型を表します。詳細は以下の通りです:

{
    ELEMENT_NODE: 1, // 元素节点
    ATTRIBUTE_NODE: 2, // 属性节点
    TEXT_NODE: 3, // 文本节点
    DATA_SECTION_NODE: 4,
    ENTITY_REFERENCE_NODE: 5,
    ENTITY_NODE: 6,
    PROCESSING_INSTRUCTION_NODE: 7,
    COMMENT_NODE: 8, // 注释节点
    DOCUMENT_NODE: 9, // 文档
    DOCUMENT_TYPE_NODE: 10,
    DOCUMENT_FRAGMENT_NODE: 11, // 文档碎片
    NOTATION_NODE: 12,
    DOCUMENT_POSITION_DISCONNECTED: 1,
    DOCUMENT_POSITION_PRECEDING: 2,
    DOCUMENT_POSITION_FOLLOWING: 4,
    DOCUMENT_POSITION_CONTAINS: 8,
    DOCUMENT_POSITION_CONTAINED_BY: 16,
    DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC: 32
}

NodeList

NodeListオブジェクトは、ノード。通常、返される Node.childNodes 、 document.getElementsByName 、および document.querySelectorAll で構成されます。

ただし、Node.childNodes と document.getElementsByName によって返される NodeList の結果はリアルタイムであるのに対し (現時点では HTMLCollection と同様)、document.querySelectorAll によって返される結果は固定されており、これは非常に特殊であることに注意してください。 。

例:

var childNodes = document.body.childNodes;
console.log(childNodes.length); // 如果假设结果是“2”
document.body.appendChild(document.createElement('p'));
console.log(childNodes.length); // 此时的输出是“3”

HTMLCollection

HTMLCollection は、複数の要素を含む一般的なコレクションを表す特別な NodeList です (要素の順序はドキュメント フロー内の順序です)。要素が変更されると、自動的に更新されます。また、擬似配列なので配列のように操作したい場合は Array.prototype.slice.call(nodeList, 2) のように呼び出す必要があります。

ノード検索 API

  • document.getElementById: ID に基づいて要素を検索します。大文字と小文字が区別されます。複数の結果がある場合は、最初の結果のみが返されます。

  • document.getElementsByClassName: クラスに基づいて要素を検索します。複数のクラス名はスペースで区切られ、HTMLCollection が返されます。互換性は IE9+ (両端を含む) であることに注意してください。さらに、ドキュメントだけでなく、他の要素も getElementsByClassName メソッドをサポートします。

  • document.getElementsByTagName: タグに基づいて要素を検索します。* はすべてのタグをクエリして HTMLCollection を返すことを意味します。

  • document.getElementsByName: 要素の name 属性に基づいて検索し、NodeList を返します。

  • document.querySelector: 単一のノード、IE8+ (両端を含む) を返します。複数の結果が一致した場合は、最初のノードのみが返されます。

  • document.querySelectorAll: NodeList、IE8+ (これを含む) を返します。

  • document.forms: 現在のページ上のすべてのフォームを取得し、HTMLCollection を返します。

ノード作成 API

ノード作成 API には主に、createElement、createTextNode、cloneNode、createDocumentFragment の 4 つのメソッドが含まれています。

createElement

要素の作成:

var elem = document.createElement("p");
elem.id = 'test';
elem.style = 'color: red';
elem.innerHTML = '我是新创建的节点';
document.body.appendChild(elem);

createElement によって作成された要素はドキュメント オブジェクトに属しません。追加するには、appendChild や insertBefore などのメソッドを呼び出す必要があります。 HTMLドキュメントの途中に追加します。

createTextNode

テキストノードを作成します:

var node = document.createTextNode("我是文本节点");
document.body.appendChild(node);

cloneNode

ノードをクローンします:node.cloneNode(true/false)。これは、子要素をコピーするかどうかを示すブールパラメータを受け取ります。

var from = document.getElementById("test");
var clone = from.cloneNode(true);
clone.id = "test2";
document.body.appendChild(clone);

7c44e228916a0ba857090b7d794510e094b3e26ee717c64999d7867364b1b4a3 を使用してイベントがバインドされている場合を除き、ノードを複製してもイベントは複製されません。addEventListener と node.onclick=xxx; を使用すると、指定されたものは何もコピーされません。 。

createDocumentFragment

このメソッドは、軽量のドキュメントを表す DocumentFragment を作成するために使用され、主に多数の DOM を操作する際のパフォーマンスを大幅に向上させることができます。

ul に 10,000 li を追加する必要がある質問があるとします。まず、文字列を結合する最も単純な方法を使用します:

<ul id="ul"></ul>
<script>
(function()
{
    var start = Date.now();
    var str = &#39;&#39;;
    for(var i=0; i<10000; i++) 
    {
        str += &#39;<li>第&#39;+i+&#39;个子节点</li>&#39;;
    }
    document.getElementById(&#39;ul&#39;).innerHTML = str;
    console.log(&#39;耗时:&#39;+(Date.now()-start)+&#39;毫秒&#39;); // 44毫秒
})();
</script>

その後、1 つずつ追加する方法に変更します。言うまでもなく、この方法は間違いありません。非効率:

<ul id="ul"></ul>
<script>
(function()
{
    var start = Date.now();
    var str = &#39;&#39;, li;
    var ul = document.getElementById(&#39;ul&#39;);
    for(var i=0; i<10000; i++)
    {
        li = document.createElement(&#39;li&#39;);
        li.textContent = &#39;第&#39;+i+&#39;个子节点&#39;;
        ul.appendChild(li);
    }
    console.log(&#39;耗时:&#39;+(Date.now()-start)+&#39;毫秒&#39;); // 82毫秒
})();
</script>

最後にドキュメント断片化メソッドを試します。このメソッドが 2 番目のメソッドよりもはるかに優れていることは明らかですが、最初のメソッドほど高速ではないはずです:

<ul id="ul"></ul>
<script>
(function()
{
    var start = Date.now();
    var str = &#39;&#39;, li;
    var ul = document.getElementById(&#39;ul&#39;);
    var fragment = document.createDocumentFragment();
    for(var i=0; i<10000; i++)
    {
        li = document.createElement(&#39;li&#39;);
        li.textContent = &#39;第&#39;+i+&#39;个子节点&#39;;
        fragment.appendChild(li);
    }
    ul.appendChild(fragment);
    console.log(&#39;耗时:&#39;+(Date.now()-start)+&#39;毫秒&#39;); // 63毫秒
})();
</script>

ノード変更 API

すべてノード変更 API には次の機能があります:

  1. ノードが追加されるか置換されるかに関係なく、元の位置にあるノードは削除されます。

  2. 変更後、イベントはバインドされます。

appendChild

これは実際に何度も使用されています。構文は次のとおりです:

parent.appendChild(child);

これは、親の子ノードの末尾に子を追加します。また、追加したノードがページ内に存在するノードの場合、実行後にノードは新しい場所に追加され、元の場所からは削除されます。つまり、ノードが 2 つ存在することはありません。同時にページとそのイベントが残ります。

insertBefore

別のノードの前にノードを挿入します。構文:

parentNode.insertBefore(newNode, refNode);

这个API个人觉得设置的非常不合理,因为插入节点只需要知道newNode和refNode就可以了,parentNode是多余的,所以jQuery封装的API就比较好:

newNode.insertBefore(refNode); // 如 $("p").insertBefore("#foo");

所以切记不要把这个原生API和jQuery的API使用方法搞混了!为了加深理解,这里写一个简单的例子:

<p id="parent">
    我是父节点
    <p id="child">
        我是旧的子节点
    </p>
</p>
<input type="button" id="insertNode" value="插入节点" />
<script>
var parent = document.getElementById("parent");
var child = document.getElementById("child");
document.getElementById("insertNode").addEventListener(&#39;click&#39;, function()
{
    var newNode = document.createElement("p");
    newNode.textContent = "我是新节点";
    parent.insertBefore(newNode, child);
}, false);
</script>

关于第二个参数:

  • refNode是必传的,如果不传该参数会报错;

  • 如果refNode是undefined或null,则insertBefore会将节点添加到末尾;

removeChild

removeChild用于删除指定的子节点并返回子节点,语法:

var deletedChild = parent.removeChild(node);

deletedChild指向被删除节点的引用,它仍然存在于内存中,可以对其进行下一步操作。另外,如果被删除的节点不是其子节点,则将会报错。一般删除节点都是这么删的:

function removeNode(node)
{
    if(!node) return;
    if(node.parentNode) node.parentNode.removeChild(node);
}

replaceChild

replaceChild用于将一个节点替换另一个节点,语法:

parent.replaceChild(newChild, oldChild);

节点关系API

DOM中的节点相互之间存在着各种各样的关系,如父子关系,兄弟关系等。

父关系API

  • parentNode :每个节点都有一个parentNode属性,它表示元素的父节点。Element的父节点可能是Element,Document或DocumentFragment;

  • parentElement :返回元素的父元素节点,与parentNode的区别在于,其父节点必须是一个Element元素,如果不是,则返回null;

子关系API

  • children :返回一个实时的 HTMLCollection ,子节点都是Element,IE9以下浏览器不支持;

  • childNodes :返回一个实时的 NodeList ,表示元素的子节点列表,注意子节点可能包含文本节点、注释节点等;

  • firstChild :返回第一个子节点,不存在返回null,与之相对应的还有一个 firstElementChild ;

  • lastChild :返回最后一个子节点,不存在返回null,与之相对应的还有一个 lastElementChild ;

兄弟关系型API

  • previousSibling :节点的前一个节点,如果不存在则返回null。注意有可能拿到的节点是文本节点或注释节点,与预期的不符,要进行处理一下。

  • nextSibling :节点的后一个节点,如果不存在则返回null。注意有可能拿到的节点是文本节点,与预期的不符,要进行处理一下。

  • previousElementSibling :返回前一个元素节点,前一个节点必须是Element,注意IE9以下浏览器不支持。

  • nextElementSibling :返回后一个元素节点,后一个节点必须是Element,注意IE9以下浏览器不支持。

元素属性型API

setAttribute

给元素设置属性:

element.setAttribute(name, value);

其中name是特性名,value是特性值。如果元素不包含该特性,则会创建该特性并赋值。

getAttribute

getAttribute返回指定的特性名相应的特性值,如果不存在,则返回null:

var value = element.getAttribute("id");

样式相关API

直接修改元素的样式

elem.style.color = &#39;red&#39;;
elem.style.setProperty(&#39;font-size&#39;, &#39;16px&#39;);
elem.style.removeProperty(&#39;color&#39;);

动态添加样式规则

var style = document.createElement(&#39;style&#39;);
style.innerHTML = &#39;body{color:red} #top:hover{background-color: red;color: white;}&#39;;
document.head.appendChild(style);

window.getComputedStyle

通过 element.sytle.xxx 只能获取到内联样式,借助 window.getComputedStyle 可以获取应用到元素上的所有样式,IE8或更低版本不支持此方法。

var style = window.getComputedStyle(element[, pseudoElt]);

getBoundingClientRect

getBoundingClientRect 用来返回元素的大小以及相对于浏览器可视窗口的位置,用法如下:

var clientRect = element.getBoundingClientRect();

clientRect是一个 DOMRect 对象,包含width、height、left、top、right、bottom,它是相对于窗口顶部而不是文档顶部,滚动页面时它们的值是会发生变化的。

一般的な JavaScript ネイティブ DOM 操作 API の概要

 

以上就是JavaScript常见原生DOM操作API总结的内容,更多相关内容请关注PHP中文网(www.php.cn)!

 

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。