Javascript DOM 筆記

DOM簡單來說就是一套js訪問Document對象的一套增刪改查規(guī)則,文檔由許多節(jié)點構成,需要重點關注的有Element、Document、Text、Attribute四種節(jié)點。

每種節(jié)點具有一些公共的屬性,包括nodeType、nodeName、nodeValue、parentNode、nextSibling、previousSibling、nextElementSibling、previousElementSibling、ownerDocument、childNodes(類數(shù)組對象),其中 parentNode、nextSibling、previousSibling、firstChild、lastChild、nextElementSibling、previousElementSibling、firstElementChild、lastElementChild 如果不存在則為 null

var parent1 = document.getElementById("parent1");
var div1 = document.getElementById("div1");
var div2 = document.getElementById("div2");

console.log(div1.nodeName);        //DIV,自動轉為大寫
console.log(div1.nodeType);        //1
console.log(div1.nodeValue);       //null

每個節(jié)點都有一個childNodes屬性,保存著一個NodeList對象。NodeList對象是一個類數(shù)組對象,動態(tài)的、實時的

  console.log(parent1.childNodes[1]);             //<div id="div1">This is a div</div>,在chrome中換行也被當做了一個節(jié)點,所以在獲取node節(jié)點時,最好先判斷一下nodeType
  //上面代碼等價于下面代碼
  console.log(parent1.childNodes.item(1));        //<div id="div1">This is a div</div>

  //非IE8以下的寫法
  var arr = Array.prototype.slice.call(someNode.childNodes, 0);       //childNodes轉化為數(shù)組對象
  var newarr = Array.prototype.slice.call(arguments, 0);          //arguments類數(shù)組轉化為數(shù)組對象

  //可以用下面的代碼將一個nodeList轉化為一個數(shù)組對象,兼容IE8
  function convertToArray(nodes1) {
    var array1 = null;
    try {
      array1 = Array.prototype.slice.call(nodes1, 0);         //針對非IE瀏覽器
    } catch (ex) {
      array1 = new Array();
      for (var i = 0; i < array1.length; i++) {
        array1.push(nodes1[i]);
      }
    }
    return array1;
  }

  console.log(div1.nextSibling);          //#text

操作節(jié)點的方法有

someNode.appendChild(newNode) 末尾追加節(jié)點,返回追加的節(jié)點

someNode.insertBefore(newNode,null) 在parent節(jié)點的子節(jié)點的某個位置插入節(jié)點,返回插入的節(jié)點,如果后一個參數(shù)為null,則效果等同appendChild()

someNode.replaceChild(newNode, someNode.firstChild) 在parent節(jié)點的子節(jié)點中用新節(jié)點替換子節(jié)點中的一項

someNode.removeChild(someNode.firstChild) 在parent節(jié)點的子節(jié)點中移除

cloneNode(true) 克隆節(jié)點,不克隆事件,IE會復制事件,所以在復制節(jié)點前,先移除事件;當參數(shù)為true時,復制子節(jié)點

  var div3 = document.createElement("div");
  var returnedNode1 = div1.appendChild(div3);
  console.log(returnedNode1 == div3);        //true
  console.log(div1.lastChild == div3);       //true

傳入文檔的新節(jié)點是現(xiàn)在文檔的一部分,則結果是將該節(jié)點從原來的位置轉移到新位置。任何DOM節(jié)點不能同時出現(xiàn)在文檔的多個位置上。

  var returnedNode2 = parent1.appendChild(parent1.firstChild);
  console.log(returnedNode2 == parent1.firstChild);        //false
  console.log(returnedNode2 == parent1.lastChild);        //true

  var returnedNode3 = parent1.insertBefore(div3, null);    //插入成為最后一個節(jié)點
  console.log(div3 == parent1.lastChild);             //true

  var returnedNode4 = parent1.insertBefore(div3, parent1.firstChild);         //返回插入的元素
  console.log(returnedNode4 == div3);            //true;
  console.log(div3 == parent1.firstChild);       //true

  //替換節(jié)點replaceChild() 移除節(jié)點removeChild()
  var returnedNode5 = parent1.removeChild(div3, parent1.firstChild);
  console.log(returnedNode5);            //<div></div>
  var returnedNode6 = parent1.removeChild(parent1.lastChild);
  console.log(returnedNode6);            //<div id="div1">This is a div</div>


  var ul1 = document.getElementById("ul1");
  var deepList = ul1.cloneNode(true);
  console.log(deepList);             //<ul id="ul1"><li>item1</li><li>item2</li><li>item3</li></ul>

  var shallowList = ul1.cloneNode();
  console.log(shallowList);          //<ul id="ul1"></ul>

Document類型
document實例 》 HTMLDocument類型 》 Document類型
JS通過Document類型表示文檔。在瀏覽器中,document對象是HTMLDocument(繼承自Document類型)的一個實例,表示整個HTML頁面
document也是window的一個屬性,可以直接訪問

  var html1 = document.documentElement;          //獲取對<html>的引用
  var html2 = document.childNodes[0];            //通過childNodes間接獲取
  var body1 = document.body;                     //直接獲取body
  var doctype1 = document.doctype;               //取得對<!DOCTYPE>的引用,有兼容性問題
  var originTitle1 = document.title;
  var url1 = document.URL;               //獲取完整url
  var domain1 = document.domain;         //獲取一級域名例:www.baidu.com
  var referrer1 = document.referrer;

  document.write();
  document.writeIn();

Element元素
HTML元素 》 HTML子類型 》 HTMLElement類型 》 Element類型

查找元素的方法
docuement.getElementById();
document.getElementsByTagName(); 返回一個HTMLCollection對象,也是一個動態(tài)集合。HTMLCollection有l(wèi)ength屬性、item()、namedItem()方法

特性
所有HTML元素都由HTMLElement類型表示,不是直接通過這個類型,也是通過它的子類型來表示。HTMLElement類型直接繼承自Element并添加了一些屬性。添加的這
些屬性分別對應于每個HTML元素中都存在的下列標準特性。
id
title
lang
dir
className

取得特性
getAttribute(); 可以取得自定義特性。

setAttribute(); 設置的特性名會自動轉化為小寫

removeAttribute();

根據(jù)HTML5規(guī)范,自定義特性應該加上data-前綴以便驗證。最上面的五種直接用js的方法來操作比較快,其他自定義屬性用getAttribute 或者setAttribute等方法

通過js的方法來操作屬性

  var div = document.getElementById("div1");
  console.log(div.id, div.className, div.title, div.lang, div.dir);
  //設置
  div.id = "newDiv";

  //通過node節(jié)點的方式來獲取
  div.getAttribute("id");
  div.getAttribute("class");
  //獲取自定義特性
  div.getAttribute("data-selfAttribute");

有兩類特殊的屬性,他們雖然有對應的屬性名,但是屬性的值與通過getAttribute()返回的值并不相同,即style和onclick處理函數(shù)
getAttribute()返回的值是字符串;
.style返回的是一個對象

創(chuàng)建元素

  var div = document.createElement("div");           //傳入標簽名
  var div = document.createElement("<div class=\"aaaa\">hello world!</div>");           //傳入一段html文本

  //遍歷時的注意事項
  for (var i = 0; var len = element.childNodes.length;i < len;i++){
    if (element.childNodes[i].nodeType == 1) {
      //do something ,先判斷類型再執(zhí)行操作
    }
  }

操作文本節(jié)點的方法有

appendData(text):將text添加到節(jié)點末尾
deleteData(offset,count):從offset指定的位置開始刪除count個字符
insertData(offset,text):在offset處插入指定的字符串
replaceData(offset,count,text):用text替換從fosset指定的位置開始到offset+count出的字符串
splitText(offset):從offset指定的位置將當前文本節(jié)點分為兩個文本節(jié)點。
substringData(offset,count):提取從offset指定的位置開始到fooset+count位置處的字符串

//創(chuàng)建文本節(jié)點并添加到div中

  var div = document.createElement("div");
  div.className = "aaa";

  var text = document.createTextNode("Hello world!");
  div.appendChild(text);

  document.body.appendChild(div);

通過normallize和splitText兩個方法來拼合文本節(jié)點和打斷文本節(jié)點

  var element = document.createElement("div");
  element.className = "message";

  var textNode1 = document.createTextNode("This is the first node, ");
  element.appendChild(textNode1);

  var textNode2 = document.createTextNode("This is the another node");
  element.appendChild(textNode2);

  document.body.appendChild(element);

  console.log(element.childNodes.length);             //2

  element.normalize();
  console.log(element.childNodes.length);                 //1
  console.log(element.firstChild.nodeValue);              //This is the first node, This is the another node,

  element.firstChild.splitText(10);                       //注意操作的是子節(jié)點
  console.log(element.childNodes.length);                 //2
  console.log(element.firstChild);                        //This is th


  document.querySelector();
  document.querySelectorAll()

//跨瀏覽器遍歷所有元素

  var i,
    len,
    child = element.firstChild;
  while (child != element.lastChild) {
    if (child.nodeType === 1) {
      processChild(child);
    }
    child = child.nextSibling;
  }

//使用element traversal遍歷

  var i,
    len,
    child = element.firstElementChild;
  while (child != element.lastElementChild) {
    processChild(child);
    child = child.nextElementSibling;
  }

HTML5新增一種該操作類名的方式classList,它是一個類似于nodelist的對象,有屬性,有方法
length
add(value):將給定的字符串值添加到類表中,如果值已經(jīng)存在了,就不添加了
contains(value):表示列表中是否存在給定的值,如果存在則返回true,否則返回false。
remove(value):從列表中刪除給定的字符串。
toggle(value):

  div.classList.remove("disabled");
  div.classList.add("current");
  div.classList.toggle("user");

確定元素中是否包含既定的類名

  if (div.classList.contains("bd") && !div.classList.contains("disabled")) {
    //執(zhí)行操作
  }
  //迭代類名
  for (var i = 0; len = div.classList.length; i < len;i++){
    doSomthing(div.classList[i]);
  }
  //動態(tài)腳本設置
  function loadScript(url){
    var script = document.createElement("script");
    script.type = "text/javascript";
    script.src = url;
    document.body.appendChild(script);
  }
  loadScript("client.js");          //不知道何時加載完畢

  //動態(tài)樣式表
  function loadStyles(url) {
    var link = document.createElement("link");
    link.rel = "stylesheet";
    link.type = "text/css";
    link.href = url;
    var head = document.getElementsByTagName("head")[0];
    head.appendChild(link);
  }
  loadStyles("client.css")          //不知道何時加載完畢

HTML5單獨增加的API

document.querySelector() 根據(jù)css規(guī)則來選擇元素,返回第一個匹配元素,沒有則返回null

document.querySelectorAll() 根據(jù)css規(guī)則來選擇元素,返回一個 NodeList 對象,沒有則返回空的 NodeList

matchesSelector() 如果調用元素與該選擇符匹配,則返回true,否則,返回false;例子:

if(document.body.matchesSelector("body.page1")){ //true}

getElementsByClassName("className1 className2 ...")         通過className選取元素,返回nodeList對象

classList屬性 一個class的屬性對象。擁有add(value) contains(value) remove(value) toggle(value) 四個方法,方便操作class

document.activeElement屬性 始終指向DOM當中當前獲得了焦點的元素
默認情況下,文檔剛剛加載完成時,document.activeElement中保存的是document.body元素的引用。文檔加載期間,document.activeElement的值為null。

document.hasFocus() 確定文檔是否獲得了焦點,頁面中的元素獲得了焦點,再調用document.hasFocus() 返回true,代表用戶正在與頁面交互

readyState屬性 文檔是否已經(jīng)加載完畢的指示器,其值有兩個loading和complete 示例:

if(document.readyState == "complete"){ //... }

compatMode兼容模式屬性 標準模式其值為CSS1Compat,混雜模式為BackCompat 示例:

if(document.compatMode == "CSS1Compat"){//...}else {/...}

document.head屬性 直接獲取head引用,示例:

var head = document.head || document.getElementsByTagName("head")[0]

document.charset字符集屬性

data- 自定義數(shù)據(jù)屬性,目的是提供與渲染無關的是信息,或者提供語義信息。 設置好之后,可以通過元素的dataset屬性來訪問
如果是駝峰寫法,則會自動將駝峰分開來,轉變成小寫。

innerHTML 對應元素的子元素,設置值時只會替換子節(jié)點的內容,盡量把所有元素拼接成字符串后再append

outterHTML 設置時,會替換節(jié)點本身

scrollIntoView()方法 針對容器 該方法可以在所有HTML元素上調用,通過滾動瀏覽器窗口或某個容器元素,調用元素就可以出現(xiàn)再是口中。如果傳入true,則調用元素會盡可能頂部與視口平齊。如果傳入false,則調用元素會近可能全部出現(xiàn)在視口中,頂部不一定平齊。

contains方法 判斷某個節(jié)點是不是另一個節(jié)點的后代 示例:

  * alert(document.documentElement.contains(document.body));        //true

下面三個方法,safari 和 chrome實現(xiàn)了
scrollIntoViewIfNeeded(alignCenter) 針對容器 只在當前元素再視口中公布可見的情況下,才滾動瀏覽器窗口或容器元素 alignCenter 設置為true時,會盡可能出現(xiàn)在視口中部

scrollByLines(lineCount) 針對元素 將元素的內容滾動指定的行高,正值和負值均可

scrollByPages(pageCount) 針對元素 將元素的內容滾動指定的頁面高度,具體高度有元素的高度決定。

myDiv.style 獲取元素樣式,其中style里面包含的只有行間樣式,沒有嵌套和引用的

document.defaultView.getComputedStyle(element,null).color 獲取計算后的樣式,包括瀏覽器默認樣式, 第二個參數(shù)通常設置為null

cuttentStyle屬性 IE中不支持getComputedStyle 方法,但是有相同的屬性來獲取計算后的樣式,注意border不能一次性獲取,因為有四條邊

offsetHeight 包括上下border padding
offsetWidth
offsetTop 元素的左外邊框至包含元素的左內邊框之間的像素距離,其中offsetLeft 和 offsetTop 屬性與包含元素有關,
包含元素的引用保存再offsetParent屬性中。offsetParent 屬性不一定與parentNode的值相等。例如td元素的offsetParent 是
作為其祖先元素的table,因為table是DOM層次中距離td最近的一個具有大小的元素
offsetLeft

clientHeight 包含內容、上下padding,不包含上下border
clientWidth

scrollHeight 不包含滾動條,元素內容的總高度
scrollWidth
scrollLeft 被隱藏在padding左邊的內容寬度,包含border
scrollTop

  //自定義屬性示例:
  var div = document.getElementById("mydiv");
    //設置自定義屬性
  div.dataset.appId = "45124";

  //獲取自定義屬性
  var appId = div.dataset.appId;
  var myName = div.dataset.myName;

焦點管理
HTML5添加了輔助管理DOM焦點的功能。首先就是,這個屬性始終會引用DOM中當前獲得焦點的元素。
元素獲得焦點的方式有頁面載入、用戶輸入和在代碼中調用focus()方法

  var button = document.getElementById("myButton");
  button.focus();
  alert(document.activeElement === button);           //true

  var button = document.getElementById("myButton");
  button.focus();
  alert(document.hasFocus());             //true,證明用戶正在與頁面交互

  function getElementLeft(element) {
    var actualLeft = element.offsetLeft;
    var current = element.offsetParent;            //offsetParent相鄰父元素

    while (current !== null) {
      actualLeft += current.offsetLeft;
      current = current.offsetParent;
    }
    return actualLeft;
  }

  function getElementTop(element) {
    var actualTop = element.offsetTop;
    var current = element.offsetParent;

    while (current !== null) {
      actualTop += current.offsetTop;
      current = current.offsetParent;
    }
    return actualTop;
  }

  /*獲取客戶區(qū)大小*/
  function getViewport() {
    if (document.compatMode == "BackCompat") {
      return {
        width: document.body.clientWidth,
        height: document.body.clientHeight
      }
    } else {
      return {
        width: document.documentElement.clientWidth,
        height: document.documentElement.clientHeight
      }
    }
  }

  //確定文檔總高度
  var docHeight = Math.max(document.documentElement.scrollHeight, document.documentElement.clientHeight);
  var docWidth = Math.max(document.documentElement.scrollWidth, document.documentElement.clientWidth);

  function scrollToTop(element) {
    if (element.screenTop != 0) {
      element.screenTop = 0;
    }
  }


  //確定元素大小
  function getBoundingClientRect(element) {
    var scrollTop = document.documentElement.scrollTop;
    var scrollLeft = document.documentElement.scrollLeft;
    if (element.getBoundingClientRect) {
      if (typeof arguments.callee.offset != "number") {
        var temp = document.createElement("div");
        temp.style.cssText = "position: absolute; left: 0; top: 0;";
        document.body.appendChild(temp);
        arguments.callee.offset = -temp.getBoundingClientRect().top - scrollTop;
        document.body.removeChild(temp);
        temp = null;
      }
      var rect = element.getBoundingClientRect();
      var offset = arguments.callee.offset;

      return {
        left: rect.left + offset,
        right: rect.right + offset,
        top: rect.top + offset,
        bottom: rect.bottom + offset
      }
    } else {
      var actualLeft = getElementLeft(element);
      var actualTop = getElementTop(element);
      return {
        left: actualLeft - scrollLeft,
        right: actualLeft + element.offsetWidth - scrollLeft,
        top: actualTop - scrollTop,
        bottom: actualTop + element.offsetHeight - scrollTop
      }
    }
  }
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容