Javascript DOM 笔记

DOM简单来说就是一套js访问Document对象的一套增删改查规则,文档由许多节点构成,需要重点关注的有Element、Document、Text、Attribute四种节点。

每种节点具有一些公共的属性,包括nodeType、nodeName、nodeValue、parentNode、nextSibling、previousSibling、nextElementSibling、previousElementSibling、ownerDocument、childNodes(类数组对象),其中 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

每个节点都有一个childNodes属性,保存着一个NodeList对象。NodeList对象是一个类数组对象,动态的、实时的

  console.log(parent1.childNodes[1]);             //
This is a div
,在chrome中换行也被当做了一个节点,所以在获取node节点时,最好先判断一下nodeType //上面代码等价于下面代码 console.log(parent1.childNodes.item(1)); //
This is a div
//非IE8以下的写法 var arr = Array.prototype.slice.call(someNode.childNodes, 0); //childNodes转化为数组对象 var newarr = Array.prototype.slice.call(arguments, 0); //arguments类数组转化为数组对象 //可以用下面的代码将一个nodeList转化为一个数组对象,兼容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

操作节点的方法有

someNode.appendChild(newNode) 末尾追加节点,返回追加的节点

someNode.insertBefore(newNode,null) 在parent节点的子节点的某个位置插入节点,返回插入的节点,如果后一个参数为null,则效果等同appendChild()

someNode.replaceChild(newNode, someNode.firstChild) 在parent节点的子节点中用新节点替换子节点中的一项

someNode.removeChild(someNode.firstChild) 在parent节点的子节点中移除

cloneNode(true) 克隆节点,不克隆事件,IE会复制事件,所以在复制节点前,先移除事件;当参数为true时,复制子节点

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

传入文档的新节点是现在文档的一部分,则结果是将该节点从原来的位置转移到新位置。任何DOM节点不能同时出现在文档的多个位置上。

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

  var returnedNode3 = parent1.insertBefore(div3, null);    //插入成为最后一个节点
  console.log(div3 == parent1.lastChild);             //true

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

  //替换节点replaceChild() 移除节点removeChild()
  var returnedNode5 = parent1.removeChild(div3, parent1.firstChild);
  console.log(returnedNode5);            //
var returnedNode6 = parent1.removeChild(parent1.lastChild); console.log(returnedNode6); //
This is a div
var ul1 = document.getElementById("ul1"); var deepList = ul1.cloneNode(true); console.log(deepList); //
  • item1
  • item2
  • item3
var shallowList = ul1.cloneNode(); console.log(shallowList); //

    Document类型
    document实例 》 HTMLDocument类型 》 Document类型
    JS通过Document类型表示文档。在浏览器中,document对象是HTMLDocument(继承自Document类型)的一个实例,表示整个HTML页面
    document也是window的一个属性,可以直接访问

      var html1 = document.documentElement;          //获取对的引用
      var html2 = document.childNodes[0];            //通过childNodes间接获取
      var body1 = document.body;                     //直接获取body
      var doctype1 = document.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对象,也是一个动态集合。HTMLCollection有length属性、item()、namedItem()方法

    特性
    所有HTML元素都由HTMLElement类型表示,不是直接通过这个类型,也是通过它的子类型来表示。HTMLElement类型直接继承自Element并添加了一些属性。添加的这
    些属性分别对应于每个HTML元素中都存在的下列标准特性。
    id
    title
    lang
    dir
    className

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

    setAttribute(); 设置的特性名会自动转化为小写

    removeAttribute();

    根据HTML5规范,自定义特性应该加上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节点的方式来获取
      div.getAttribute("id");
      div.getAttribute("class");
      //获取自定义特性
      div.getAttribute("data-selfAttribute");
    

    有两类特殊的属性,他们虽然有对应的属性名,但是属性的值与通过getAttribute()返回的值并不相同,即style和onclick处理函数
    getAttribute()返回的值是字符串;
    .style返回的是一个对象

    创建元素

      var div = document.createElement("div");           //传入标签名
      var div = document.createElement("
    hello world!
    "); //传入一段html文本 //遍历时的注意事项 for (var i = 0; var len = element.childNodes.length;i < len;i++){ if (element.childNodes[i].nodeType == 1) { //do something ,先判断类型再执行操作 } }

    操作文本节点的方法有

    appendData(text):将text添加到节点末尾
    deleteData(offset,count):从offset指定的位置开始删除count个字符
    insertData(offset,text):在offset处插入指定的字符串
    replaceData(offset,count,text):用text替换从fosset指定的位置开始到offset+count出的字符串
    splitText(offset):从offset指定的位置将当前文本节点分为两个文本节点。
    substringData(offset,count):提取从offset指定的位置开始到fooset+count位置处的字符串

    //创建文本节点并添加到div中

      var div = document.createElement("div");
      div.className = "aaa";
    
      var text = document.createTextNode("Hello world!");
      div.appendChild(text);
    
      document.body.appendChild(div);
    

    通过normallize和splitText两个方法来拼合文本节点和打断文本节点

      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);                       //注意操作的是子节点
      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):将给定的字符串值添加到类表中,如果值已经存在了,就不添加了
    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")) {
        //执行操作
      }
      //迭代类名
      for (var i = 0; len = div.classList.length; i < len;i++){
        doSomthing(div.classList[i]);
      }
      //动态脚本设置
      function loadScript(url){
        var script = document.createElement("script");
        script.type = "text/javascript";
        script.src = url;
        document.body.appendChild(script);
      }
      loadScript("client.js");          //不知道何时加载完毕
    
      //动态样式表
      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() 根据css规则来选择元素,返回第一个匹配元素,没有则返回null

    document.querySelectorAll() 根据css规则来选择元素,返回一个 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属性 文档是否已经加载完毕的指示器,其值有两个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- 自定义数据属性,目的是提供与渲染无关的是信息,或者提供语义信息。 设置好之后,可以通过元素的dataset属性来访问
    如果是驼峰写法,则会自动将驼峰分开来,转变成小写。

    innerHTML 对应元素的子元素,设置值时只会替换子节点的内容,尽量把所有元素拼接成字符串后再append

    outterHTML 设置时,会替换节点本身

    scrollIntoView()方法 针对容器 该方法可以在所有HTML元素上调用,通过滚动浏览器窗口或某个容器元素,调用元素就可以出现再是口中。如果传入true,则调用元素会尽可能顶部与视口平齐。如果传入false,则调用元素会近可能全部出现在视口中,顶部不一定平齐。

    contains方法 判断某个节点是不是另一个节点的后代 示例:

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

    下面三个方法,safari 和 chrome实现了
    scrollIntoViewIfNeeded(alignCenter) 针对容器 只在当前元素再视口中公布可见的情况下,才滚动浏览器窗口或容器元素 alignCenter 设置为true时,会尽可能出现在视口中部

    scrollByLines(lineCount) 针对元素 将元素的内容滚动指定的行高,正值和负值均可

    scrollByPages(pageCount) 针对元素 将元素的内容滚动指定的页面高度,具体高度有元素的高度决定。

    myDiv.style 获取元素样式,其中style里面包含的只有行间样式,没有嵌套和引用的

    document.defaultView.getComputedStyle(element,null).color 获取计算后的样式,包括浏览器默认样式, 第二个参数通常设置为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;
      }
    
      /*获取客户区大小*/
      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
          }
        }
      }
    

    你可能感兴趣的:(Javascript DOM 笔记)