第十章 DOM

第十章 DOM

  • DOM文档对象模型 是针对HTML和XML文档的一个API(应用程序编程接口)
  • IE中所有DOM对象都是以COM对象实现的,与原生JS对象的行为或活动特点并不一致

10.1 节点层次

  • 文档节点是每个文档的根节点
  • 称为元素,是文档的最外层元素

10.1.1 Node类型

  • DOM1级定义了一个Node接口,由DOM中的所有节点类型实现
  • 这个Node接口在JS中是作为Node类型实现的,除IE所有浏览器可访问到这个类型
  • 任何节点类型必居其一:
NodeType Named Constant
1 ELEMENT_NODE
2 ATTRIBUTE_NODE
3 TEXT_NODE
4 CDATA_SECTION_NODE
5 ENTITY_REFERENCE_NODE
6 ENTITY_NODE
7 PROCESSING_INSTRUCTION_NODE
8 COMMENT_NODE
9 DOCUMENT_NODE
10 DOCUMENT_TYPE_NODE
11 DOCUMENT_FRAGMENT_NODE
12 NOTATION_NODE
var someNode = document.getElementById('test');
if(someNode.nodeType == 1){ //适用于所有浏览器
    console.log("Node is an element");
}
nodeName nodeValue
//<p id="test">aaa</p>
var someNode = document.getElementById('test');
if(someNode.nodeType == 1){
    //适用于所有浏览器
    console.log(someNode.nodeName); //元素标签名 P
    console.log(someNode.nodeValue);//null
}
节点关系
  • 每个节点都有childNodes属性,其中保存着NodeList类数组对象
  • NodeList是有生命,可呼吸的对象,并非在第一次访问它们某个瞬间拍下的快照
  • 访问方法
var firstChild = someNode.childNodes[0]; //推荐
var secondChild = someNode.childNodes.item(1);
var count = someNode.childNodes.length;
  • NodeList转换成数组
function convertToArray(nodes){
    var array = null;
    try{
        array = Array.prototype.slice.call(nodes, 0);
    }catch(ex){
        //兼容IE8
        array = new Array();
        for(var i=0, len=nodes.length; i < len; i++){
            array.push(nodes[i]);
        }
    }
    return array;
}
  • 常见属性 无值时为null

    • parentNode
    • childNodes[n]
    • previousSibling
    • nextSibling
    • fisrstChild
    • lastChild
    • ownerDocument 直接回溯到顶端文档节点
    • childNodes.length
  • 常用方法

    • hasChildNodes()
操作节点
  • appendChild() 如果插入自身拥有的节点,相当于调换了顺序
<div class="box" id="box">
	<div class="box_1">
		<div class="box_1_1">box_1_1</div>
		<div class="box_1_2">box_1_2</div>
		<div class="box_1_3">box_1_3</div>
	</div>
	<div class="box_2">
		<div class="box_2_1">box_2_1</div>
		<div class="box_2_2">box_2_2</div>
		<div class="box_2_3">box_2_3</div>
	</div>
	<div class="box_3">
		<div class="box_3_1">box_3_1</div>
		<div class="box_3_2">box_3_2</div>
		<div class="box_3_3">box_3_3</div>
	</div>
</div>
var someNode = document.getElementById('box');
var newNode = document.createElement('div');
newNode.innerText = '新增节点';
var returnedNode = someNode.appendChild(newNode);
var returnedNode = someNode.appendChild(someNode.firstChild);
console.log(returnedNode == someNode.firstChild); //false
console.log(returnedNode == someNode.lastChild); //true
  • insertBefore(新节点,旧参照位置节点)
var returnedNode = someNode.insertBefore(newNode, someNode.firstChild); //最前
var returnedNode = someNode.insertBefore(newNode, null); //最后
  • replaceChild 替换节点
var returnedNode = someNode.replaceChild(newNode, someNode.firstChild); 
  • removeChild 移除节点
var returnedNode = someNode.removeChild(someNode.firstChild); 
其他方法
  • cloneNode()
    • 传入true进行深复制 会复制节点及其整个子节点树
    • 不传入时仅复制本身
  • normalize() 处理文档树中的文本节点
    • 解析器可能出现文本节点不含文本 或出现两个文本节点
    • 调用这个方法可以删除空文本节点 或合并相邻为一个文本节点

10.1.2 Document类型

  • JS通过Document类型表示文档
  • 在浏览器中 document对象是HTMLDocument(继承自Document类型)的一个实例,表示整个HTML页面
  • document对象是window对象的一个属性,可以作为全局对象访问
  • document节点特征
    • nodeType: 9
    • nodeName: "#document"
    • nodeValue: null
    • parentNode: null
    • ownerDocument null
    • 子节点可能是:DocumentType Element ProcessingInstruction Comment
文档的子节点
  • document.documentElement 取得对的引用
  • document.childNodes[n]
  • document.firstChild
  • document.body
  • document.doctype //取得对<!DOCTYPE>的引用 浏览器的支持差别很大
文档信息
  • 作为HTMLDocument的一个实例,document对象还有一些标准Document对象所没有的属性
  • title
var originalTitle = document.title;
document.title = "New title";
  • URL 完整URL
  • domain 域名
  • referrer 来源页面的URL
//假设页面雷子phone.baidu.com域
document.domain = "baidu.com"; //成功 子级可访问父级 
document.domain = "taobao.com"; //失败 不能设置url中不包含的域
查找元素 (最常见)
  • getElementById(id)
    • 严格匹配id 区分大小写
    • IE7怪癖:如果表单元素id和name相同 则该方法会返回元素而非元素引用
  • getElementsByTagName()
    • 返回HTMLCollection对象动态集合 和NodeList类似
// <img src="myimg.gif" name="myImg">
var images = document.getElementsByTagName("img");
console.log(images.length);
console.log(images[0].src);
console.log(images.item(0).src);

var myImg = images.namedItem("myImg");
var myImg = images["myImg"];

//返回所有元素 IE会包含注释
document.getElementsByTagName("*");
  • getElementsByName()
    • HTMLDocument类型才有的方法 返回给定name特性的所有元素
    • 一般取单选按钮
特殊集合
  • 都是HTMLCollection对象 集合项目会动态变化
  • document.anchors 包含文档中所有带name特性的a元素
  • document.links 包含文档中所有带href特性的a元素
  • document.forms 包含文档中所有form元素 等于 document.getElementsByTagName("form")
  • document.images 包含文档中所有form元素 等于 document.getElementsByTagName("img")
DOM一致性检测
  • DOM分多级 含有多个部分,所以需要检测实现了DOM的哪些部分
  • 最好除了检测hasFeature()之外 还同时使用能力检测
var hasXmlDom = document.implementation.hasFeature("XML","1.0");
文档写入
  • document.write()
  • document.writeln()
  • document.open()
  • document.close()

10.1.3 Element类型(最常见之一)

  • 提供对元素标签名、子节点及特性的访问
  • Element类型具有以下特征
    • nodeType为1
    • nodeName为元素标签名
    • nodeValue为null
    • parentNode可能是Document或Element
  • 访问元素标签名 可以使用nodeName 也可以使用tagName
//<div id="mydiv">test</div>
var div = document.getElementById("mydiv");
console.log(div.tagName); //DIV
console.log(div.tagName == div.nodeName); //true
  • 一般使用element.tagName.toLowerCase() == "div"
HTML元素
  • id title className
  • lang dir
var div = document.getElementById("mydiv");
console.log(div.id); //mydiv
div.title = "somediv";
取得特性
getAttribute()
  • 注意
    • 特性名要与实际相同 如element.getAttribute("class") 而非className
    • 不存在返回null
    • 不区分大小写
    • H5规范里 自定义特性应该加上data-前缀
  • 两类特殊特性
    • style
      • console.log(div.style); //返回对象
      • console.log(div.getAttribute('style')); //返回文本
    • onclick
      • 属性访问 返回函数或null
      • getAttribute访问 返回字符串
setAttribute()
  • div.setAttribute("id", "someId");
  • div.setAttribute("data-show", "false"); //自定义特性会自动转小写
  • 如果通过对象形式添加自定义属性 则不会自动成为元素特性
removeAttribute()
attributes属性
  • 比较少用 可以遍历
 function outputAttributes(element){
    var pairs = new Array(),
        attrName,
        attrValue,
        i,
        len;

    for (i=0, len=element.attributes.length; i < len; i++){
        attrName = element.attributes[i].nodeName;
        attrValue = element.attributes[i].nodeValue;
        if (element.attributes[i].specified){
            pairs.push(attrName + "=\"" + attrValue + "\"");
        }
    }
    return pairs.join(" ");
}
创建元素
  • document.createElement("div");
元素的子节点
for(var i=0, len=element.childNodes.length; i<len;i++){
    if(element.childNodes[i].nodeType == 1){
        //...
    }
}
var ul = document.getElementById("myList");
var items = ul.getElementsByTagName("li");

10.1.4 Text类型

  • 纯文本内容 可以包含转义后的HTML字符
  • 具有以下特征
    • nodeType为3
    • nodeName为"#text"
    • nodeValue为所包含的文本
    • parentNode是一个Element
    • 不支持子节点
修改 element.firstChild.NodeValue="xxx"
创建 document.createTextNode()
规范 element.normalize()
分割 element.splitText()

10.1.5 Comment类型:注释

  • 创建 document.createComment()

10.1.6 CDATASection类型

  • 只针对XML

10.1.7 DocumentType类型

  • 包含文档doctype所有信息

10.1.8 DocumentFragment类型

  • 轻量级文档 可以作为临时仓库使用
function addItems(){
    var fragment = document.createDocumentFragment();
    var ul = document.getElementById("myList");
    var li = null;
    for (var i=0; i < 3; i++){
        li = document.createElement("li");
        li.appendChild(document.createTextNode("Item " + (i+1)));
        fragment.appendChild(li);
    }
    ul.appendChild(fragment);    
}

10.1.9 Attr类型

10.2 DOM操作技术

10.2.1 动态脚本

  • 加载外部JS文件是异步的
var script = document.createElement("script");
script.type = "text/javascript";
script.src = "client.js";
document.body.appendChild(script);
<body>
    <p>You should see an alert saying &quot;hi&quot; after clicking the button.</p>
    <input type="button" value="Add Script" onclick="addScript()">

    <script type="text/javascript">
    
        function loadScriptString(code){
            var script = document.createElement("script");
            script.type = "text/javascript";
            try {
                script.appendChild(document.createTextNode(code));
            } catch (ex){
                script.text = code;
            }
            document.body.appendChild(script);
        }
    
        function addScript(){
            loadScriptString("function sayHi(){alert('hi');}");
            sayHi();
        }

    </script>
</body>

10.2.2 动态样式

  • 加载外部样式文件是异步的
var link = document.createElement("link");
link.rel = "stylesheet";
link.type = "text/css";
link.href = "style.css";
var head = document.getElementByTagName("head")[0];
head.appendChild(link);
function loadStyleString(css){
    var style = document.createElement("style");
    style.type = "text/css";
    try{
        style.appendChild(document.createTextNode(css));
    } catch (ex){
        style.styleSheet.cssText = css;
    }
    var head = document.getElementsByTagName("head")[0];
    head.appendChild(style);
}

function addStyle(){
    loadStyleString("body{background-color:red}"); 
}

10.2.3 操作表格

  • [拓展] 10.2.3 JS操作表格常用方法
  • tbody.insertRow(0);

10.2.4 使用NodeList

  • 近亲:NamedNodeMap、HTMLCollection
  • 动态更新
posted @ 2019-10-08 17:52  KevinTseng  阅读(93)  评论(0编辑  收藏  举报