JavaScript DOM编程艺术 第七章 动态创建标记 笔记

7 动态创建标记

7.1 本章内容

  • 传统技术:document.write()和innerHTML属性
  • 深入刨析DOM方法:createElement()、createTextNode()、appendChild()、insertBefore()

之前几章使用get方法获取文档特定元素节点,使用setAttributes方法(改变某个属性的值)、nodeValue(改变某个元素节点所包含的文本)之类来处理。
本章通过DOM方法,创建和修改现有元素。

7.2 一些传统方法

7.2.1 document.write()

document.write()方法可以向文档中写入HTML代码,但是只能在页面加载完成后执行,而且只能写入一次。

document.write("<h1>Hello World</h1>");
<html>
  <head>
    <title>Document.write()</title>
  </head>   
    <body>
      <h1>This is the original content</h1>
      <script>
        document.write("<h1>Hello World</h1>");
      </script>
    </body>
</html>

很大的缺点,违背行为和结构分离的原则。
XHTML中不允许使用document.write()方法。 使用中应该避免使用document.write()方法。

7.2.1 innerHTML属性

innerHTML属性可以获取或设置元素的innerHTML内容,可以直接写入HTML代码。

<div id="myDiv">
<p>This is <em>my</em> content</p>
</div>

对于innerHTML, id为myDiv元素只有一个子元素p内的全部
对DOM来说,元素节点div,存在属性节点id="myDiv"和子元素节点p。子元素节点p包含文本节点"This is “、元素节点em、文本节点 " content” 即DOM树。

总结来说,innerHTML像是一把大树,子元素是一大坨;DOM就像手术刀十分精细

innerHTML属性可以直接写入HTML代码,会覆盖原有的所容。

document.getElementById("myDiv").innerHTML = "<p>This is <em>my</em> new content</p>";

当需要插入大量HTML代码时,使用innerHTML属性会非常方便。

下面来看下DOM方法

7.3 DOM方法

DOM是文档的表示。DOM包含的信息与文档的信息一一对应,DOM可以获取DOM树上任意一个节点的细节

DOM不但可以获取文档内容,也可以创建和修改文档内容。 但是,setAttribute()方法只能修改元素的属性。在不使用浏览器时,看不到界面的变化

想在节点树上添加内容,就必须要插入新元素节点。

7.3.1 createElement()

创建test.html文件,在body标签中添加一个div元素。

<div id="myDiv"></div>
  1. 创建新的元素节点。
  2. 把新元素节点添加到文档树中。
window.onload = function() {
    var para = document.createElement("p");
    var info = "nodeName: "
    info += para.nodeName;  // nodeName: P
    info += " nodeType: "
    info += para.nodeType;  // nodeType: 1
    alert(info);
}

创建了一个新的元素节点para,取值为p的nodeName属性,nodeType属性为1。

7.3.2 appendChild()

appendChild()方法可以把一个元素节点添加到另一个元素节点的子节点列表中。

var para = document.createElement("p");
var testDiv = document.getElementById("myDiv");
testDiv.appendChild(para);

上述代码创建了一个新的元素节点para,并把它添加到id为myDiv的元素节点的子节点列表中。

7.3.3 createTextNode()

createTextNode()方法可以创建文本节点。
在上节创建了p元素节点,但是没有文本内容。

下面为p创建文本内容,然后将文本内容插入myDiv元素节点中。

var para = document.createElement("p");
var text = document.createTextNode("This is a new paragraph.");
para.appendChild(text);

var testDiv = document.getElementById("myDiv");
testDiv.appendChild(para);

7.3.4 一个更复杂的组合

实现html代码如下:

<div id="myDiv">
<p>This is <em>my</em> content</p>
</div>
window.onload = function() {
    var para = document.createElement("p");
    var text = document.createTextNode("This is");
    para.appendChild(text);

    var em = document.createElement("em");
    var text2 = document.createTextNode(" my");
    em.appendChild(text2);
    para.appendChild(em);

    var text3 = document.createTextNode(" content");
    para.appendChild(text3);

    var testDiv = document.getElementById("myDiv");
    testDiv.appendChild(para);
}

7.4 重回图片库

跳过了,实现图片库的html代码如下:

<img id="placeholder" src="image/gallery.webp" alt="placeholder">
<p id="description">选择一个图片</p>
  1. 创建一个img元素节点,设置src属性为"image/gallery.webp",alt属性为"placeholder"。
  2. 创建一个p元素节点,设置id属性为"description"。
  3. 把img元素节点和p元素节点添加到文档树中。
window.onload = function() {    
    var img = document.createElement("img");
    img.src = "image/gallery.webp";
    img.alt = "placeholder";

    var p = document.createElement("p");
    p.id = "description";
    p.innerHTML = "选择一个图片";

    var placeholder = document.getElementById("placeholder");
    var description = document.getElementById("description");

    placeholder.body.appendChild(img);
    placeholder.body.appendChild(p);
}

7.4.1 在已有元素前插入一个元素

insertBefore()方法可以把一个元素节点插入到另一个元素节点的子节点列表中,并指定插入位置。

在元素前插入元素需要知道三件事

  1. 目标元素
  2. 新元素
  3. 插入位置(父元素)

调用insertBefore()方法

parentElement.insertBefore(newElement, targetElement);

对于父元素,DOM中,元素节点的父元素必须是另一个元素节点。(属性节点和文本节点的子元素不允许是元素节点)
因此,在插入元素前,需要先获取父元素。

var img = document.createElement("img");
img.parentNode.insertBefore(placeholder, img);

获取img元素的父元素,并把placeholder元素插入到兄弟元素img之前。

7.4.2 在现有元素后插入一个元素

有了insertBefore()方法,我们希望有个insertAfter()方法,但是DOM没有提供。

7.4.2.1 编写insertAfter()方法
function insertAfter(newElement, targetElement)

思路:

  1. 将newElement插入到targetElement的之后
  2. 如果targetElement是最后一个子元素,则将newElement插入到父元素的子节点列表的最后。
  3. 如果targetElement不是最后一个子元素,则将newElement插入到targetElement的之前

首先,DOM的nextSibling属性可以获取某个元素节点的下一个兄弟元素节点。

function insertAfter(newElement, targetElement) {
    var parent = targetElement.parentNode;
    if (targetElement.nextSibling) {
        parent.insertBefore(newElement, targetElement.nextSibling);
    } else {
        parent.appendChild(newElement);
    }
}

解释:

  1. 获取目标元素的父元素
  2. 如果目标元素有下一个兄弟元素,则将新元素插入到下一个兄弟元素之前
  3. 如果目标元素没有下一个兄弟元素,则将新元素插入到父元素的子节点列表的最后。
7.4.2.2 使用insertAfter()方法
function preparePlaceholder() {
    if (!document.getElementById) return false;
    if (!document.createElement) return false;
    if (!document.createTextNode) return false;
    if (!document.getElementById("imageGallery")) return false;


    var placeholder = document.createElement("img");
    placeholder.src = "image/gallery.webp";  // placeholder.setAttribute("src", "image/gallery.webp");
    placeholder.alt = "placeholder";  // placeholder.setAttribute("alt", "placeholder");
    placeholder.id = "placeholder";  // placeholder.setAttribute("id", "placeholder");


    var description = document.createElement("p");
    description.id = "description";  // description.setAttribute("id", "description");
    var descText = document.createTextNode("选择一个图片");
    description.appendChild(descText);

    var gallery = document.getElementById("imageGallery");
    insertAfter(placeholder, gallery);
    insertAfter(description, placeholder);
}
<body>
    <h1>图片库</h1>
    <ui id="imageGallery">
        <li><a href="image/toWest/monkey.webp" title="悟空"><img src="image/toWest/monkey.webp" alt="悟空"></a></li>
    </ui>
    <!-- <img id="placeholder" src="image/gallery.webp" alt="placeholder">   新增元素 -->
    <!-- <p id="description">选择一个图片</p> 新增元素 --> 
    <script type="text/javascript" src="scripts/showPic.js"></script>
</body>

这里就把图片库的结构、样式和脚本彻底分开了。

那么,如何得到原来不属于初始页面的内容?

7.5 AJAX

AJAX(Asynchronous JavaScript and XML)是一种Web开发技术,它允许Web页面与服务器异步通信,实现Web页面的局部更新。

用户点击了某个链接,请求发送回服务器,服务器根据用户操作再返回新的页面。使用AJAX可以实现无刷新页面,即用户操作页面时,不用刷新页面,只更新局部内容。

7.5.1 XMLHttpRequest对象

XMLHttpRequest对象是AJAX的核心对象,它提供了异步请求的功能。XMLHttpRequest对象充当客户端和服务器之间的通信通道。

ajax.html文件如下:

<!DOCTYPE html>
<html>
<head>  
    <meta charset="UTF-8">
    <title>AJAX</title>
</head>
<body>
    <div id="new"></div>
    <script src="scripts/addLoadEvent.js"></script>
    <script src="scripts/getHTTPObject.js"></script>
    <script src="scripts/getNewContent.js"></script>

</body>
</html>

在scripts文件夹下,分别编写三个js文件:

  • addLoadEvent.js:添加onload事件
  • getHTTPObject.js:获取XMLHttpRequest对象
  • getNewContent.js:获取新内容

为了模拟服务器响应,在ajax.html文件旁,创建example.txt文件,内容如下:

这是异步加载

模拟服务端脚本输出。

对getHTTPObject.js文件,如下:

function getHTTPObject() {
    if (typeof XMLHttpRequest == "undefined") {
        XMLHttpRequest = function() {
            try {
                return new ActiveXObject("Msxml2.XMLHTTP.6.0");}
                catch (e) {}
            try {
                return new ActiveXObject("Microsoft.XMLHTTP");}
                catch (e) {}
            try {
                return new ActiveXObject("Msxml2.XMLHTTP.3.0");}     
    }
    return new XMLHttpRequest();
}
  • 首先,判断浏览器是否支持XMLHttpRequest对象。
  • 如果支持,则使用XMLHttpRequest对象。
  • 如果不支持,则使用ActiveXObject对象。
  • 如果都不支持,则返回false。

在获取XMLHttpRequest对象时

var request = getHTTPObject();

XMLHttpRequest对象提供了很多方法,比如open()、send()、setRequestHeader()等。
最有用的是open()方法,它用于设置请求的类型、URL和是否异步。

对于getNewContent.js文件,如下:

function getNewContent() {
    var request = getHTTPObject();
    if (request) {
        request.open("GET", "example.txt", true);
        request.onreadystatechange = function() {
            if (request.readyState == 4 && request.status == 200) {
                var para = document.createElement("p");
                var text = document.createTextNode(request.responseText);
                para.appendChild(text);
                document.getElementById("new").appendChild(para);
            }
        };
        request.send(null);
    } else {
        alert("Sorry, your browser does not support AJAX.");
    }
}
  • 首先,获取XMLHttpRequest对象。
  • 如果对象存在,则使用open()方法设置请求的类型、URL和是否异步。
  • 设置onreadystatechange事件处理函数,当请求状态改变时,调用该函数。
  • 调用send()方法发送请求。
  • 如果请求成功,则获取服务器响应,并创建新的元素节点和文本节点,并添加到id为new的元素节点的子节点列表中。
  • 如果请求失败,则弹出提示信息。

服务器向XMLHttpRequest对象发回响应时,浏览器可能有许多属性可用,浏览器在不同节点更新readyState属性的值。

  • 0:请求未初始化。
  • 1:服务器连接已建立。
  • 2:请求已接收。
  • 3:表示正在交互
  • 4:表示完成

访问服务器返回数据通过两个属性完成

  • responseText:返回字符串形式的响应数据。
  • responseXML:返回XML形式的响应数据。用于保存Content-Type: text/xml的响应数据。其实是DocumentFragment对象。

注意:
同源策略(Same-origin policy)是一种约定,它规定了AJAX请求只能从同一个源服务器发送。使用XMLHttpRequest对象时,只能访问与其所在HTML页面同源的资源,不能向其他域发送请求

有些浏览器限制ajax请求使用的协议

对于异步性,脚本在发送XMLHttpRequest对象时,任会继续执行,在脚本结束增加告警框,可能会先看到告警框提示内容,再看到新内容。

function getNewContent() {
    var request = getHTTPObject();
    if (request) {
        request.open("GET", "example.txt", true);
        request.onreadystatechange = function() {
            if (request.readyState == 4 && request.status == 200) {
                var para = document.createElement("p");
                var text = document.createTextNode(request.responseText);
                para.appendChild(text);
                document.getElementById("new").appendChild(para);
            }
        };
        request.send(null);
    } else {
        alert("Sorry, your browser does not support AJAX.");
    }
    alert("New content loaded.");
}

7.6 总结

本章介绍了DOM方法,创建和修改现有元素。

  • createElement()方法可以创建新的元素节点。
  • appendChild()方法可以把一个元素节点添加到另一个元素节点的子节点列表中。
  • createTextNode()方法可以创建文本节点。
  • insertBefore()方法可以把一个元素节点插入到另一个元素节点的子节点列表中,并指定插入位置。
  • insertAfter()方法可以把一个元素节点插入到另一个元素节点的子节点列表中,并指定插入位置。

AJAX是一种Web开发技术,它允许Web页面与服务器异步通信,实现Web页面的局部更新。

XMLHttpRequest对象是AJAX的核心对象,它提供了异步请求的功能。XMLHttpRequest对象充当客户端和服务器之间的通信通道。

  • 14
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值