美文网首页
Javascript DOM 笔记

Javascript DOM 笔记

作者: 冬瓜不削皮 | 来源:发表于2019-01-13 19:20 被阅读0次

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]);             //<div id="div1">This is a div</div>,在chrome中换行也被当做了一个节点,所以在获取node节点时,最好先判断一下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转化为数组对象
  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);            //<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对象,也是一个动态集合。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("<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 ,先判断类型再执行操作
    }
  }

操作文本节点的方法有

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 笔记

      本文链接:https://www.haomeiwen.com/subject/lkgmzftx.html