ホームページ > 記事 > ウェブフロントエンド > 一般的な JavaScript ネイティブ DOM 操作 API の概要
最近のインタビュー中にこの質問に行き詰まったので、時間をかけて注意深く見直しました。
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オブジェクトは、ノード。通常、返される 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 は、複数の要素を含む一般的なコレクションを表す特別な NodeList です (要素の順序はドキュメント フロー内の順序です)。要素が変更されると、自動的に更新されます。また、擬似配列なので配列のように操作したい場合は Array.prototype.slice.call(nodeList, 2) のように呼び出す必要があります。
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 には主に、createElement、createTextNode、cloneNode、createDocumentFragment の 4 つのメソッドが含まれています。
要素の作成:
var elem = document.createElement("p"); elem.id = 'test'; elem.style = 'color: red'; elem.innerHTML = '我是新创建的节点'; document.body.appendChild(elem);
createElement によって作成された要素はドキュメント オブジェクトに属しません。追加するには、appendChild や insertBefore などのメソッドを呼び出す必要があります。 HTMLドキュメントの途中に追加します。
テキストノードを作成します:
var node = document.createTextNode("我是文本节点"); document.body.appendChild(node);
ノードをクローンします: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; を使用すると、指定されたものは何もコピーされません。 。
このメソッドは、軽量のドキュメントを表す DocumentFragment を作成するために使用され、主に多数の DOM を操作する際のパフォーマンスを大幅に向上させることができます。
ul に 10,000 li を追加する必要がある質問があるとします。まず、文字列を結合する最も単純な方法を使用します:
<ul id="ul"></ul> <script> (function() { var start = Date.now(); var str = ''; for(var i=0; i<10000; i++) { str += '<li>第'+i+'个子节点</li>'; } document.getElementById('ul').innerHTML = str; console.log('耗时:'+(Date.now()-start)+'毫秒'); // 44毫秒 })(); </script>
その後、1 つずつ追加する方法に変更します。言うまでもなく、この方法は間違いありません。非効率:
<ul id="ul"></ul> <script> (function() { var start = Date.now(); var str = '', li; var ul = document.getElementById('ul'); for(var i=0; i<10000; i++) { li = document.createElement('li'); li.textContent = '第'+i+'个子节点'; ul.appendChild(li); } console.log('耗时:'+(Date.now()-start)+'毫秒'); // 82毫秒 })(); </script>
最後にドキュメント断片化メソッドを試します。このメソッドが 2 番目のメソッドよりもはるかに優れていることは明らかですが、最初のメソッドほど高速ではないはずです:
<ul id="ul"></ul> <script> (function() { var start = Date.now(); var str = '', li; var ul = document.getElementById('ul'); var fragment = document.createDocumentFragment(); for(var i=0; i<10000; i++) { li = document.createElement('li'); li.textContent = '第'+i+'个子节点'; fragment.appendChild(li); } ul.appendChild(fragment); console.log('耗时:'+(Date.now()-start)+'毫秒'); // 63毫秒 })(); </script>
すべてノード変更 API には次の機能があります:
ノードが追加されるか置換されるかに関係なく、元の位置にあるノードは削除されます。
変更後、イベントはバインドされます。
これは実際に何度も使用されています。構文は次のとおりです:
parent.appendChild(child);
これは、親の子ノードの末尾に子を追加します。また、追加したノードがページ内に存在するノードの場合、実行後にノードは新しい場所に追加され、元の場所からは削除されます。つまり、ノードが 2 つ存在することはありません。同時にページとそのイベントが残ります。
別のノードの前にノードを挿入します。構文:
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('click', function() { var newNode = document.createElement("p"); newNode.textContent = "我是新节点"; parent.insertBefore(newNode, child); }, false); </script>
关于第二个参数:
refNode是必传的,如果不传该参数会报错;
如果refNode是undefined或null,则insertBefore会将节点添加到末尾;
removeChild用于删除指定的子节点并返回子节点,语法:
var deletedChild = parent.removeChild(node);
deletedChild指向被删除节点的引用,它仍然存在于内存中,可以对其进行下一步操作。另外,如果被删除的节点不是其子节点,则将会报错。一般删除节点都是这么删的:
function removeNode(node) { if(!node) return; if(node.parentNode) node.parentNode.removeChild(node); }
replaceChild用于将一个节点替换另一个节点,语法:
parent.replaceChild(newChild, oldChild);
DOM中的节点相互之间存在着各种各样的关系,如父子关系,兄弟关系等。
parentNode :每个节点都有一个parentNode属性,它表示元素的父节点。Element的父节点可能是Element,Document或DocumentFragment;
parentElement :返回元素的父元素节点,与parentNode的区别在于,其父节点必须是一个Element元素,如果不是,则返回null;
children :返回一个实时的 HTMLCollection ,子节点都是Element,IE9以下浏览器不支持;
childNodes :返回一个实时的 NodeList ,表示元素的子节点列表,注意子节点可能包含文本节点、注释节点等;
firstChild :返回第一个子节点,不存在返回null,与之相对应的还有一个 firstElementChild ;
lastChild :返回最后一个子节点,不存在返回null,与之相对应的还有一个 lastElementChild ;
previousSibling :节点的前一个节点,如果不存在则返回null。注意有可能拿到的节点是文本节点或注释节点,与预期的不符,要进行处理一下。
nextSibling :节点的后一个节点,如果不存在则返回null。注意有可能拿到的节点是文本节点,与预期的不符,要进行处理一下。
previousElementSibling :返回前一个元素节点,前一个节点必须是Element,注意IE9以下浏览器不支持。
nextElementSibling :返回后一个元素节点,后一个节点必须是Element,注意IE9以下浏览器不支持。
给元素设置属性:
element.setAttribute(name, value);
其中name是特性名,value是特性值。如果元素不包含该特性,则会创建该特性并赋值。
getAttribute返回指定的特性名相应的特性值,如果不存在,则返回null:
var value = element.getAttribute("id");
elem.style.color = 'red'; elem.style.setProperty('font-size', '16px'); elem.style.removeProperty('color');
var style = document.createElement('style'); style.innerHTML = 'body{color:red} #top:hover{background-color: red;color: white;}'; document.head.appendChild(style);
通过 element.sytle.xxx 只能获取到内联样式,借助 window.getComputedStyle 可以获取应用到元素上的所有样式,IE8或更低版本不支持此方法。
var style = window.getComputedStyle(element[, pseudoElt]);
getBoundingClientRect 用来返回元素的大小以及相对于浏览器可视窗口的位置,用法如下:
var clientRect = element.getBoundingClientRect();
clientRect是一个 DOMRect 对象,包含width、height、left、top、right、bottom,它是相对于窗口顶部而不是文档顶部,滚动页面时它们的值是会发生变化的。
以上就是JavaScript常见原生DOM操作API总结的内容,更多相关内容请关注PHP中文网(www.php.cn)!