对象和dom

w3c建议符合标准的浏览器采用节点操纵(node manipulation)的方式支持网页,使页面表现得更像应用程序,而不是一般的标准静态页面。例如,可以让页面在不与服务器进行通信的情况下,根据用户输入的内容发生改变,以及在脚本的控制下更新页面。节点操纵也可以在服务器端实现,但是如果要提供这个功能,同时又不必迫使用户在页面之间不断移动,那么只能使用JavaScript。
文档对象模型(Document Object Model,DOM)。
JavaScript 可以称为“组合式(snap-together)语言”,因为可以将对象、属性和方法组合在一起来构建出JavaScript 应用程序。还有一种看待HTML 页面的方式:将它看作由节点
(node)组成的树结构。
在这里插入图片描述
可以使用JavaScript 修改这个树结构的任何方面,包括添加、访问、修改和删除树中的节点。这个树中的每个框都是一个节点。如果一个节点包含HTML 标签,那么它就称为元素节点(element node)。否则,它称为文本节点(text node)。当然,元素节点可以包含文本节点。
学习节点最容易的方法,是首先在文档末尾追加一个元素节点

添加文本节点

这个HTML 创建一个文本区域和一个提交按钮,让用户能够添加文本节点:

<!DOCTYPE html>
<html>
<head>
<title>Adding Nodes</title>
<script src="script01.js"></script>
</head>
<body>
<form id="theForm">
<p><textarea id="textArea" rows="5"cols="30"></textarea></p>
<input type="submit" value="Add some text to the page">
</form>
</body>
</html>

这个脚本使用户可以将任何文本添加到页面上

window.addEventListener("load",initAll,false);
function initAll() {
document.getElementById("theForm").addEventListener("submit",addNode,false);
}
function addNode(evt) {
var inText = document.getElementById("textArea").value;
var newText = document.createTextNode(inText);/*使用createTextNode()方法创建一个新的文本节点(名为newText)它将包含在textArea中找到的文本。*/
var newGraf = document.createElement("p");/*接下来,使用createElement()方法创建一个新的元素节点。尽管这里创建的节点是一个段落标签,但它也可以是任何HTML 容器(div、span 等)。这个新元素的名称是newGraf。*/
newGraf.appendChild(newText);
/*为了将新文本添加到新段落中,我们必须调用appendChild()。这是newGraf 元素的一个方法,将newText 传递给它时,就会将文本节点放进段落中。*/
var docBody = document.getElementsByTagName("body")[0];
/*为了将新节点添加到文档的body 中,需要查明body 的位置。这个getElementsByTagName()方法会给出页面上的每个body 标签。如果页面符合标准,那么应该只有一个body 标签。[0]属性是第一个body 标签,我们将它存储在docBody 中。*/
docBody.appendChild(newGraf);
/*最后,将newGraf 追加到docBody 中(同样使用appendChild()),从而将用户输入的新文本放到页面上。*/
evt.preventDefault();
}

效果:
在这里插入图片描述
既然对innerHTML 进行简单的赋值就可以实现同样的效果,那么为什么要这么费事儿(创建文本节点、创建元素节点并且追加子节点)呢?有一个原因:利用这种方式,就不可能导致页面无效。例如,添加的每个

标签会自动结束。另一方面,如果使用innerHTML,就非常容易形成无效的标签(简直太容易了)。一旦发生这种情况,页面的DOM 就很难处理了。
例如,如果一个元素有开始标签,而没有结束标签,那么就无法读取这个元素的内容。
 段落本身不能再包含段落。如果你试图传入多个用空行分隔的句子,这段代码将把它们合并成一个大段,而不是分别解析每一段。

删除节点

这个脚本添加一个用来删除文本节点的链接(而不是按钮)

<!DOCTYPE html>
<html>
<head>
<title>Deleting Nodes</title>
<script src="script01.js"></script>
</head>
<body>
<form id="theForm">
<p><textarea id="textArea" rows="5" cols="30"></textarea></p>
<input type="submit" value="Add some text to the page">
</form>
<a href="#"id="deleteNode" >Delete last paragraph</a>
</body>
</html>

js:现在,用户既可以添加文本,也可以删除文本

window.addEventListener("load",initAll,false);
function initAll() {
document.getElementById("theForm").addEventListener("submit",addNode,false);
document.getElementById("deleteNode").addEventListener("click",delNode,false);
}
function addNode(evt) {
var inText = document.getElementById("textArea").value;
var newText = document.createTextNode(inText);
var newGraf = document.createElement("p");
newGraf.appendChild(newText);
var docBody = document.getElementsByTagName("body")[0];
docBody.appendChild(newGraf);
evt.preventDefault();
}
function delNode(evt) {
var allGrafs = document.getElementsByTagName("p");
/*这一行使用getElementsByTagName 方法收集页面上的所有段落标签,并且将它们存储在allGrafs数组中。*/
if (allGrafs.length > 1) {
/*在进行实际的删除操作之前,首先必须检查allGrafs 数组的长度是否大于1。我们不希望尝试删除某些并不存在的东西,而且数组的长度总是至少为1*/
var lastGraf = allGrafs[allGrafs.length-1];
/*如果有段落,那么以数组长度减1 作为数组索引来获得最后一个段落。请记住,长度是从1 开始的,而数组索引是从0 开始的,所以数组长度减1 就可以获得页面上的最后一个段落*/
var docBody = document.getElementsByTagName("body")[0];
docBody.removeChild(lastGraf);
/*与前一节中相似,为了修改文档,需要找到body 的内容。在此之后,只需调用docBody.removeChild()方法并且将lastGraf 传递给它,这告诉JavaScript 我们希望删除哪个段落。在页面上,会立刻显示少了一个段落。*/
}
else {
alert("Nothing to remove!");
}
evt.preventDefault();
}

在这里插入图片描述
点击delete后:
在这里插入图片描述

删除特定的节点

单选按钮让访问者选择是添加文本,还是删除文本

<!DOCTYPE html>
<html>
<head>
<title>Deleting Selected Nodes</title>
<script src="script01.js"></script>
</head>
<body>
<form id="theForm">
<p><textarea id="textArea" rows="5"cols="30"></textarea></p>
<p>
<label><input type="radio" name="nodeAction">Add node</label>
<label><input type="radio" name="nodeAction">Delete node</label>
</p>
Paragraph #: <select id="grafCount"></select>
<input type="submit" value="Submit">
</form>
<div id="modifiable"> </div>
</body>
</html>

这个脚本让用户能够选择要删除的段落

window.addEventListener("load",initAll,false);
var nodeChgArea;
function initAll() {
document.getElementById("theForm").addEventListener("submit",nodeChanger,false);
nodeChgArea = document.getElementById("modifiable");
}
function addNode() {
var inText = document.getElementById("textArea").value;
var newText = document.createTextNode(inText);
var newGraf = document.createElement("p");
newGraf.appendChild(newText);
nodeChgArea.appendChild(newGraf);
}
function delNode() {
var grafChoice = document.getElementById("grafCount").selectedIndex;
var allGrafs = nodeChgArea.getElementsByTagName("p");
var oldGraf = allGrafs.item(grafChoice);
nodeChgArea.removeChild(oldGraf);
}
function nodeChanger(evt) {
var actionType = -1;
var pGrafCt = nodeChgArea.getElementsByTagName("p").length;
var radioButtonSet = document.getElementById("theForm").nodeAction;
for (var i=0; i<radioButtonSet.length; i++) {
if (radioButtonSet[i].checked) {
actionType = i;
}
}
switch(actionType) {
case 0:
addNode();
break;
case 1:
if (pGrafCt > 0) {
delNode();
break;
}
default:
alert("No valid action was chosen");
}
document.getElementById("grafCount").options.length = 0;
for (i=0; i<nodeChgArea.getElementsByTagName("p").length; i++) {
document.getElementById("grafCount").options[i] = new Option(i+1);
}
evt.preventDefault();
}

效果:
在这里插入图片描述
在这里插入图片描述

  1. nodeChgArea = document.getElementById(“modifiable”);
    因为HTML 页面现在有多个段落,所以不容易跟踪哪些段落可以删除,哪些不可以删除。所以,我们建立一个全新的区域:一个id 为modifiable 的div。在这里,将全局变量nodeChgArea 设置为这个元素节点。

  2. var grafChoice = document.getElementById(“grafCount”).selectedIndex;
    var allGrafs = nodeChgArea.getElementsByTagName(“p”);
    var oldGraf = allGrafs.item (grafChoice);
    当用户选择进行段落删除时,他们还必须选择要删除的段落。我们从grafCount 字段读取段落号,并且将它存储在grafChoice 中。然后,将allGrafs 变量设置为nodeChangingArea 中的所有段落,并且将要删除的段落存储在oldGraf 中。

插入节点

除了删除不在文档末尾处的节点之外,还可能希望在文档末尾之外的其他位置添加节点。通过以下脚本可以选择让新节点出现在哪里

<!DOCTYPE html>
<html>
<head>
<title>Inserting Nodes</title>
<script src="script04.js"></script>
</head>
<body>
<form id="theForm">
<p><textarea id="textArea" rows="5" cols="30"></textarea></p>
<p>
<label><input type="radio" name="nodeAction">Add node</label>
<label><input type="radio" name="nodeAction">Delete node</label>
<label><input type="radio" name="nodeAction">Insert before node</label>
</p>
Paragraph #: <select id="grafCount"></select>
<input type="submit" value="Submit">
</form>
<div id="modifiable"> </div>
</body>
</html>

用户现在可以在页面上的任何地方添加文本

window.addEventListener("load",initAll,false);
var nodeChgArea;
function initAll() {
document.getElementById("theForm").addEventListener("submit",nodeChanger,false);
nodeChgArea = document.getElementById("modifiable");
}
function addNode() {
var inText = document.getElementById("textArea").value;
var newText = document.createTextNode(inText);
var newGraf = document.createElement("p");
newGraf.appendChild(newText);
nodeChgArea.appendChild(newGraf);
}
function delNode() {
var grafChoice = document.getElementById("grafCount").selectedIndex;
var allGrafs = nodeChgArea.getElementsByTagName("p");
var oldGraf = allGrafs.item(grafChoice);
nodeChgArea.removeChild(oldGraf);
}
function insertNode() {
var grafChoice = document.getElementById("grafCount").selectedIndex;
var inText = document.getElementById("textArea").value;
var newText = document.createTextNode(inText);
var newGraf = document.createElement("p");
newGraf.appendChild(newText);
var allGrafs = nodeChgArea.getElementsByTagName("p");
var oldGraf = allGrafs.item(grafChoice);
nodeChgArea.insertBefore(newGraf,oldGraf);
}
function nodeChanger(evt) {
var actionType = -1;
var pGrafCt = nodeChgArea.getElementsByTagName("p").length;
var radioButtonSet = document.getElementById("theForm").nodeAction;
for (var i=0; i<radioButtonSet.length; i++) {
if (radioButtonSet[i].checked) {
actionType = i;
}
}
switch(actionType) {
case 0:
addNode();
break;
case 1:
if (pGrafCt > 0) {
delNode();
break;
}
case 2:
if (pGrafCt > 0) {
insertNode();
break;
}
default:
alert("No valid action was chosen");
}
document.getElementById("grafCount").options.length = 0;
for (i=0; i<nodeChgArea.getElementsByTagName("p").length; i++) {
document.getElementById("grafCount").options[i] = new Option(i+1);
}
evt.preventDefault();
}

效果:

(选择insert选项 3)
在这里插入图片描述

  1. var grafChoice = document.getElementById(“grafCount”).selectedIndex;
    var inText = document.getElementById(“textArea”).value;
    为了插入一个段落,我们需要知道两个信息:用户希望插入段落的位置(grafChoice)以及他们希望插入的文本(inText)。
  2. var newText = document.createTextNode(inText);
    var newGraf = document.createElement(“p”);
    newGraf.appendChild(newText);
    这是创建新的段落节点并且以用户文本填充它的标准方法。
  3. var allGrafs = nodeChgArea.getElementsByTagName(“p”);
    var oldGraf = allGrafs.item(grafChoice);
    同样,我们收集区域中的所有p 标签,然后将目标段落(我们将在这个段落前面插入新段落)存储在oldGraf 中。
  4. nodeChgArea.insertBefore(newGraf,oldGraf);
    插入新节点的方法是调用insertBefore()方法并且传递两个参数:新节点和一个现有的节点(新节点要插入在这个节点前面)。

方法insertBefore

HTML DOM insertBefore() 方法
HTML DOM Element 对象
语法
node.insertBefore(newnode,existingnode)
newnode Node 对象 必需。需要插入的节点对象。
existingnode Node object 可选。在其之前插入新节点的子节点。如果未规定,则 insertBefore 方法会在结尾插入 newnode。
实例
向列表中插入一个项目:

document.getElementById(“myList”).insertBefore(newItem,existingItem);
插入之前:

Coffee
Tea
插入之后:

Water
Coffee
Tea

替换节点

html中增加一行:

<label><input type="radio" name= "nodeAction">Replace node</label>
var oldGraf = allGrafs.item(grafChoice);
nodeChgArea.insertBefore(newGraf,oldGraf);
}
function replaceNode() {
var grafChoice = document.getElementById("grafCount").selectedIndex;
var inText = document.getElementById("textArea").value;
var newText = document.createTextNode(inText);
var newGraf = document.createElement("p");
newGraf.appendChild(newText);
var allGrafs = nodeChgArea.getElementsByTagName("p");
var oldGraf = allGrafs.item(grafChoice);
nodeChgArea.replaceChild(newGraf,oldGraf);
}
function nodeChanger(evt) {
var actionType = -1;
var pGrafCt = nodeChgArea.getElementsByTagName("p").length;
var radioButtonSet = document.getElementById("theForm").nodeAction;
for (var i=0; i<radioButtonSet.length; i++) {
if (radioButtonSet[i].checked) {
actionType = i;
}
}
switch(actionType) {
case 0:
addNode();
break;
case 1:
if (pGrafCt > 0) {
delNode();
break;
}
case 2:
if (pGrafCt > 0) {
insertNode();
break;
}
case 3:
if (pGrafCt > 0) {
replaceNode();
break
}
default:
alert("No valid action was chosen");
}
document.getElementById("grafCount").options.length = 0;
for (i=0; i<nodeChgArea.getElementsByTagName("p").length; i++) {
document.getElementById("grafCount").options[i] = new Option(i+1);
}
evt.preventDefault();
}
已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页