一,基本定义
DOM是针对HTML和XML文档的API,根据W3C的HTML DOM标准,html文档中所以内容(无论是元素还是标签还是注释还是元素属性)都是节点。

二,Node类型:
每一个节点都含有一个nodeType属性,对应着不同的数字,一共有12个,这里只记住前三个:
1.代表元素节点,也是最多的
2.代表属性节点,就是元素的属性,也是节点
3.代表文本,一个空格,一个回车都是代表#text节点
9.代表document文档

如果nodeType=1,元素节点,则nodeName就是标签名,注意这里是大写的(如“DIV”),nodeValue始终是null。

注意:nodeValue和innerHTML的区别
nodeValue指的是当前节点的值,这个节点是具体的,如果只是一个元素节点,那么没有任何值,它下面的子节点的值是它子节点的nodeValue,而且这个nodeValue包括所有的内容,像换行符也会包括,不是它的,所以它为null;而innerHTML指的是该节点下所有的子节点的字符串形式,包括它们的值。

html: <div id=“aa”>
    这里有一句话
   </div>

js: var aa = document.getElementById(“aa”);
aa.nodeValue; //null
aa.attributes[’id’].nodeValue; // aa
aa.childNodes[0].nodeValue; // (空行)
这里有一句话
(空行)
aa.innerHTML; // 这里有一句话

每一个节点都有一个childNodes属性,它保存着一个NodeList对象(就是你取一个节点,然后打印出来,就是这个对象,对象展开下面就是该节点下面所有的子节点),可以通过childNodes[a]来访问值,这个NodeList也有length值,它是类数组,但是它不是数组,同样不可以用数组的一些迭代运算。不过它有一个特殊的方法,item(a)可以访问到里面的子节点,
例:var secondChildNode = someNode.childNodes.item(1)。访问子节点的时候要注意,如果是常规的写法,没有写在一行里,分行写的,那么每一个换行都有一个#text节点。例如:
html: <div id=“aa”>
    <li></li>
    <li></li>
  </div>

js:
var div = document.getElementById(“aa”);
console.log(div.childNodes);

结果:
#text
li
#text
li
#text
(上面每一个都是对象,可展开的,里面就是他自身node节点属性)

如果需要把NodeList转换成数组来进行一系列的操作,可以用Array.prototype.slice()方法。不过这个方法在IE8之前无效,所以如果那样需要手动塞入:

function convertToArray(nodeList){
  var array = null;
  try{
    array = Array.prototype.slice.call(nodeList, 0);    //先检测是否是IE8之前版本
  } catch(ex){
    array = new Array();
    for(var i=0; i<nodeList.length; i++){
      array.push(nodeList[i])
    }
  }
  return array
}

三,节点属性:

parentNode: 父节点
firstChild: 第一个子节点
lastChild: 最后一个子节点
previousSibling: 前一个兄弟节点,NodeList.firstChild的这个属性一定是null
nextSibling: 后一个兄弟节点,NodeList.lastChild的这个属性一定是null
ownerDocument: 所有的节点最后一个属性都是这个,指向当前文档节点,可以直接找到它,唯一一个

四,操作节点(带child的都是操作的子节点)

appendChild(node):向子节点的末尾添加一个节点node,添加的节点必须是定义的或者是查找出来的,不能像jquery那样手动去写字符串。
例:
var newNode = document.createElement(“div”),
newText = document.createTextNode(“hello world!”);
newNode.appendChild(newText);
someNode.appendChild(newNode);

insertBefore(a, b):在子节点b前面添加一个a节点,如果b为null,则a添加至最后,和appendChild()方法一样

replaceChild(a, b): 用a节点来替换子节点b

removeChild(node):移除子节点node

cloneNode():可以传参数true,如果不传,则为浅复制,就是只复制这个节点,而不包括它的子节点,如果传了,则为深复制,会包含该节点以及它下面的所有的子节点

五,查找元素

getElementById() //ID
getElementsByTagName() //标签名,得到数组,如果传的是”*”,则表示全部
getElementsByName() //name值
getElementsByClassName() //IE5,6,7,8中无效,所以不要用这个

上面四个都是基于document对象来查找

someNode.nameItem(name) //根据name属性值来查找

六,特性值

getAttribute()
setAttribute()
removeAttribute()

可以直接给属性赋值来修改或者设置属性值,但是注意,这里的属性一定要是内部包含的(或者本身具备的属性),而不是自定义的属性
div.id = “aa”;
div.className = “cc”;

attributes属性:
每一个节点都有这个属性,该属性后可接一些方法(nodeName全部为大写)

someNode.attributes.getNamedItem(name); //获得nodeName为name的节点,注意,这里的attribute查找是在该节点的自身里面查找,而不是子节点。
等同于:someNode.attributes[name]; //简写

someNode.attributes.removeNamedItem(name); //移除nodeName为name的节点

someNode.attributes.setNamedItem(node); //设置一个新的节点,这个用的比较少,还是用setAttribute()比较好

七,创建元素
document.createElement() //元素节点
document.createTextNode() //文本节点

八,Text类型(所有的方法都是基于文本节点,offset、count都是数字,text是字符串)

appendData(text): 将text文本添加到节点末尾
deleteData(offset, count): 从offset的位置开始删除count个字符
insertData(offset, text): 从offset的位置开始添加text
replaceData(offset, count, text): 用text来替换文本,从offset开始到offset+count结束
splitText(offset): 从offset位置将当前文本节点分成两个文本节点
substringData(offset, count): 提取从offset开始到offset+count结束的文本字符串

normalize():父节点使用这个方法,将内部的文本子节点全部合并成一个,就是字符串拼接

九,DOM操作技术

动态脚本:

function loadScript(url){
    var scriptNode = document.createElement(“script”);
    scriptNode.src = url;
    scriptNode.type = “text/javascript”;
    document.body.appendChild(scriptNode);
}

动态样式:

function loadScript(url){

var cssNode = document.createElement(“link”);
  cssNode.href = url;
  cssNode.type = “text/css”;
  cssNode.rel = “stylesheet”;
  document.getElementsByTagName(“head”)[0].appendChild(cssNode);
}

=======================

DOM扩展:

1,选择器

querySelector(): 类似于jquery的选择器,传入的css选择符
querySelectorAll(): 也是传入css选择符,只不过返回的是所有的匹配到的,一个数组,相当于NodeList

2,元素遍历:
由于之前的childNodes包含文本节点、注释节点等,不利于我们去查找获取子节点,所以推出了新的API:

childElementCount: 获取子节点的个数(只是元素节点)
firstElementChild: 第一个元素子节点
lastElementChild: 最后。。。。
previousElementSibling: 。。。。
nextElementSibling: 。。。。

3,classList属性(返回的是一个DOMTokenList对象,这个对象的结构类似于这样:
{
0: ‘class1’,
1: ‘class2’,
2: ‘class3’,
value: ‘class1 class2 class3’
}
):

elementNode(元素节点).classList.add(value); 添加value类,如果有就不添加了
elementNode(元素节点).classList.contains(value); 列表中是否存在这个值,如果存在返回true,否则false
elementNode(元素节点).classList.remove(value); 删除value类
elementNode(元素节点).classList.toggle(value); 如果列表中有,就删除,没有就添加

4,焦点
focus();
document.hasFocus(); 判断文档是否获得焦点

5,document.head,目前只有Safari 5和谷歌浏览器能用,所以还是用getElementsByTagName方法

6,自定义属性

html5为元素添加自定义属性的时候,一定要用 data- 开头,目的是提供语义信息,如果要访问这个属性值,不能用div.data-myname,会报错,只能用dataset,后面跟的是 data- 后面的myname,

div.dataset.myname = 123; 设置自定义属性值

7,innderHTML属性
返回子节点所有的内容,包括元素、注释、文本,但是IE和Opera返回的是大写的,所以不同的浏览器返回的也不同。不是所有的元素都有这个属性,像table相关的都不支持这个。

8,outerHTML
返回的是包含当前节点的所有内容

9,insertAdjacentHTML()方法,两个参数

element.insertAdjacentHTML(“beforebegin”, “<p>hello</p>”); //作为前一个同辈元素插入,就是同级
element.insertAdjacentHTML(“afterbegin”, “<p>hello</p>”); //作为第一个子元素插入,是在子节点里面
element.insertAdjacentHTML(“beforeend”, “<p>hello</p>”); //作为最后一个子元素插入,也是在子节点里面
element.insertAdjacentHTML(“afterend”, “<p>hello</p>”); //作为后一个同辈元素插入

10,scrollIntoView();    // 项目中遇到的做城市列表选择右侧的首字母跳转功能
someNode.scrollIntoView(); //如果不传参数或者传true,默认节点的顶端与视口顶部平行,如果传false,默认节点的底部与视口顶部平行

11,children属性:
和childNodes差别,children只包含元素子节点,IE9以后是只包含元素节点,IE8及之前也包含注释节点

12,contains(someNode):检测某节点下是否包含此子节点

DOM3级,类似方法:compareDocumentPosition(someNode),返回值
1 //无关
2 //居前(在参考节点之前)
4 //居后
8 //包含(给定节点是参考节点的祖先)
16 //被包含(是子节点,等同于contains)

13,innerText,Firefox不支持,
和innerHTML区别,一个返回的是纯文本,不包含元素节点标签等,一个返回的html代码,包含所有节点

14,outerText
div.outerText = “hello world”;
等同于
var text = document.createTextNode(“hello world”)
div.parentNode.replaceChild(text, div)

=======================

DOM2和DOM3

DOM1级主要定义的是HTML和XML文档的底层结构,DOM2和DOM3则在这个结构的基础上引入了更多的交互能力,也支持了更高级的XML特性。

获得浏览器视口大小:

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

    }

  }  

}

监测某元素是否在顶部,如果不是就使其滚到顶部

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

JavaScript学习日志(五):DOM的更多相关文章

  1. javascript学习日志:前言

    javascript学习日志系列的所有博客,主要理论依据是<javascript权威指南>(犀牛书第6版)以及<javascript高级程序设计第三版>(红色书),目前js行业 ...

  2. JavaScript学习总结(五)——jQuery插件开发与发布

    jQuery插件就是以jQuery库为基础衍生出来的库,jQuery插件的好处是封装功能,提高了代码的复用性,加快了开发速度,现在网络上开源的jQuery插件非常多,随着版本的不停迭代越来越稳定好用, ...

  3. javascript学习 真正理解DOM脚本编程技术背后的思路和原则

    本文学习来源于<javascriptDOM编程艺术>仅作笔记 学会怎样才能利用DOM脚本编程技术以一种既方便自己更体贴用户的方式去充实和完善你们的网页. 循序渐进:从最核心的内容开始,逐步 ...

  4. javascript学习笔记之DOM与表单

    DOM(文档对象模型),猫叔了一个层次化的节点树 一.DOM NODE相关公共属性与方法 DOM中所有节点都实现了NODE接口,该接口的公共属性和方法如下: 1.节点基本属性 1)NodeType 节 ...

  5. JavaScript学习日志(六):事件

    这篇随笔,深恶痛绝,敲到快结束的时候,凌晨00:19,突然闪退,也不知道是Mac的原因还是chrome的原因,重新打开的时候,以为自动保存有效果,心想没关系,结果他么的只保存了四分之一,WTF?!!! ...

  6. javascript学习笔记之DOM

    DOM(文档对象模型),描述了一个层次化的节点树 一.DOM NODE相关公共属性与方法 DOM中所有节点都实现了NODE接口,该接口的公共属性和方法如下: 1.节点基本属性 1)NodeType 节 ...

  7. JavaScript 学习笔记-HTML&&DOM

    HTML DOM (文档对象模型) 当网页被加载时,浏览器会创建页面的文档对象模型(Document Object Model). HTML DOM 模型被构造为对象的树. JavaScript 能够 ...

  8. 【JavaScript学习整理】DOM对象(location history screen navigator)

    DOM: 描述网页各个组成部分之间的关系. parentNode: 父节点 childNode: 子节点 firstChild: 第一个子节点 lastChild: 最后一个子节点 nextSibli ...

  9. JavaScript学习笔记之DOM介绍

    目录 1.简介 2.方法 3.属性 4.访问节点 5.修改节点 6.添加节点 7.删除节点 8.替换节点 9.改变 CSS 1.简介 文档对象模型(Document Object Model,DOM) ...

随机推荐

  1. hdu 6045 Is Derek lying?(思维推导)

    Problem Description Derek and Alfia are good friends.Derek is Chinese,and Alfia is Austrian.This sum ...

  2. Springboot+redis 整合

    运行环境: JDK1.7. SpringBoot1.4.7 redis3.0.4 1.生成Springboot项目,分别添加web,redis依赖,具体的maven依赖如下 <dependenc ...

  3. DynamicXml

    /* var xml = @"<root><books><book is_read=""false""><a ...

  4. 一个普通的 Zepto 源码分析(一) - ie 与 form 模块

    一个普通的 Zepto 源码分析(一) - ie 与 form 模块 普通的路人,普通地瞧.分析时使用的是目前最新 1.2.0 版本. Zepto 可以由许多模块组成,默认包含的模块有 zepto 核 ...

  5. 安卓Service完全解析(上)

    版权声明:本文出自汪磊的博客,转载请务必注明出处. 关于安卓Service相信很多安卓开发者都听说过,作为安卓四大组件之一,即使不经常用也应该听说过,但并不是每一个人都掌握的特别详细,全面.那么今天我 ...

  6. bootstrap 切换页签失效的解决方法

    概述 bootstrap开发标签页时,标签页显示正常,但点击时候对应内容区域没有变化. 具体症状与解决方案 1.标签页UI出现,但点击无反应,标签页UI并未随点击进行切换 先检查bootstrap.c ...

  7. vue如何封装自己需要的方法

    因为现在vue的流行,vue的各种插件都出来了,我们公司也是使用vue做项目,我自己在做项目的时候自己去琢磨了其他的插件以及结合自己对vue和es2015的理解,自己找的了一种在vue中使用封装方法的 ...

  8. leetcode First Bad Version(二分查找)

    You are a product manager and currently leading a team to develop a new product. Unfortunately, the ...

  9. Monad详解

    最近几年,函数式编程变得越来越流程,其代码简洁.副作用小.维护成本低等特点,使得许多其它的语言也开始支持函数式编程,比如Java 和 C#等.本文主要介绍一下函数式编程中的一个重要概念:Monad. ...

  10. node里面的c/c++模块

    准备工作 node使用c++插件时需要使用node-gyp包,node-gyp把c++源码编译为二进制文件,js在调用二进制文件,编译后的二进制文件模块调用就和js的模块调用一样. npm insta ...