DOM编程

一、什么是DOM编程?

文档对象模型 (DOM) 是HTML和XML文档的编程接口。它提供了对文档的结构化的表述,并定义了一种方式可以使从程序中对该结构进行访问,从而改变文档的结构,样式和内容。DOM 将文档解析为一个由节点和对象(包含属性和方法的对象)组成的结构集合。简言之,它会将web页面和脚本或程序语言连接起来。简单来说:DOM编程就是使用document对象的API完成对网页HTML文档进行动态修改,以实现网页数据和样式动态变化效果的编程.

二、什么是document?

document对象代表整个html文档,可用来访问页面中的所有元素,是最复杂的一个dom对象,可以说是学习好dom编程的关键所在。

三、document对象如何获取?

document对象是window对象的一个成员属性,通过window.document来访问,当然也可以直接使用document,根据HTML代码结构特点,document对象本身是一种树形结构的文档对象。

四、DOM节点分类node

结点对象:Node,document对象中的每一个分支点都是一个node对象,它有三个子类

  1. 元素节点 Element 如:<a href="链接地址">我的链接</a>
  2. 属性节点 Attribute 如:href="链接地址"
  3. 文本节点 Text 如:我的链接

五、DOM操作的内容

  • 查询元素(获取元素,进而操作元素,或者元素的属性,文本)
  • 操作文本
  • 操作属性
  • 操作元素
  • 操作CSS样式(一个特殊的属性style)

六、Node节点常用的属性和方法

1.属性

1.1 Node.prototype.nodeType

document.nodeType // 9

不同节点的nodeType的属性值不同

  • 文档节点(document):9,对应常量Node.DOCUMENT_NODE
  • 元素节点(element):1,对应常量Node.ELEMENT_NODE
  • 属性节点(attr):2,对应常量Node.ATTRIBUTE_NODE
  • 文本节点(text):3,对应常量Node.TEXT_NODE
  • 文档片断节点(DocumentFragment):11,对应常量Node.DOCUMENT_FRAGMENT_NODE
  • 文档类型节点(DocumentType):10,对应常量Node.DOCUMENT_TYPE_NODE
  • 注释节点(Comment):8,对应常量Node.COMMENT_NODE

1.2 Node.prototype.nodeName

nodeName属性返回节点的名称

let div = document.getElementById('d1');
div.nodeName // "DIV"

不同节点的nodeName属性值不同

  • 文档节点(document):#document
  • 元素节点(element):大写的标签名
  • 属性节点(attr):属性的名称
  • 文本节点(text):#text
  • 文档片断节点(DocumentFragment):#document-fragment
  • 文档类型节点(DocumentType):文档的类型
  • 注释节点(Comment):#comment

1.3 Node.prototype.nodeValue

nodeValue属性返回一个字符串,表示当前节点本身的文本值,该属性可读写

只有文本节点(text)、注释节点(comment)和属性节点(attr)有文本值,其他类型的节点一律返回null

// <div id="d1">hello world</div>
var div = document.getElementById('d1');
div.nodeValue // null
div.firstChild.nodeValue // "hello world"

textContent属性返回当前节点和它的所有后代节点的文本内容

// <div id="box">This is <span>some</span> text</div>
document.getElementById('box').textContent
// This is some text

textContent属性会自动忽略节点内部的HTML标签,返回所有文本内容

该属性是可读写的,设置属性的值,会用一个新的文本节点替换掉所有原来的子节点

该属性会自动对HTML 标签转义

document.getElementById('box').textContent = '<p>GoodBye!</p>';
将标签解释为文本,而不会当作标签处理

1.5 Node.prototype.ownerDocument

Node.ownerDocument属性返回当前节点所在的顶层文档对象,即document对象

let div = d1.ownerDocument
console.log(div === document) //True

document对象本身的ownerDocument属性,返回null

1.6 Node.prototype.nextSibling

Node.nextSibling属性返回紧跟在当前节点后面的第一个节点,如果没有节点返回null

// <div id="d1">hello</div><div id="d2">world</div>
var d1 = document.getElementById('d1');
var d2 = document.getElementById('d2');

d1.nextSibling === d2 // true

该属性还包括文本节点和注释节点,如果节点后面有空格,该属性会返回一个文本节点

1.7 Node.prototype.previousSibling

previousSibling属性返回当前节点前面的、距离最近的一个节点。如果当前节点前面没有节点,返回null

// <div id="d1">hello</div><div id="d2">world</div>
var d1 = document.getElementById('d1');
var d2 = document.getElementById('d2');

d2.previousSibling === d1 // true

该属性还包括文本节点和注释节点,如果节点前面有空格,该属性会返回一个文本节点

1.8 Node.prototype.parentNode

parentNode属性返回当前节点的父节点

对于一个节点,他的父元素只可能是三种元素:元素节点,文档节点和文档片段节点

let div = document.getElementById("d1")
div.parentNode.removeChild(div)

上面代码,用过div.parentNode属性将div元素删除,文档节点和文档片段节点的父节点都是null

1.9 Node.prototype.parentElement

parentElement属性返回当前节点的父元素节点。如果当前节点没有父节点,或者父节点类型不是元素节点,则返回null

1.10 Node.prototype.firstChild,Node.prototype.lastChild

firstChild属性返回当前节点的第一个子节点,如果当前节点没有子节点,则返回null。

// <p id="p1"><span>First span</span></p>
var p1 = document.getElementById('p1');
p1.firstChild.nodeName // "SPAN"

firstChild返回的除了元素节点,还可能是文本节点或注释节点

// <p id="p1">
//   <span>First span</span>
//  </p>
var p1 = document.getElementById('p1');
p1.firstChild.nodeName // "#text"

p元素和span元素之间有换行,所以firstChild返回的是文本节点

lastChild属性返回当前节点的最后一个子节点,如果当前节点没有子节点,则返回null。用法与firstChild属性相同

1.11Node.prototype.childNodes

childNodes属性返回一个类似数组的对象(NodeList集合),成员包括当前节点的所有子节点。

var children = document.querySelector('ul').childNodes;
//children就是ul元素的所有子节点

该属性可以遍历某个节点的所有子节点

let div = document.getElementById("d1")
let Child = div.childNodes
for(let i = 0; i< Child.length; i++){
    //...
}

除了元素节点,childNodes属性的返回值还包括文本节点和注释节点

如果当前节点不包括任何子节点,则返回一个空的NodeList集合

NodeList对象是一个动态集合,一旦子节点发生变化,立刻会反映在返回结果之中。

1.12 Node.prototype.isConnected

isConnected属性返回一个布尔值,表示当前节点是否在文档之中

var test = document.createElement('p');
test.isConnected // false

document.body.appendChild(test);
test.isConnected // true

test节点是生成的节点,没有插入文档之前 isConnected返回的是False,插入之后返回True

2.方法

2.1 Node.prototype.appendChild()

appendChild()方法接受一个节点对象作为参数,将其作为最后一个子节点,插入当前节点,该方法的返回值就是插入文档的子节点

1
2
var p = document.createElement('p');
document.body.appendChild(p);

新建一个节点,插入body的尾部如果参数节点是已经存在的节点,appendChild方法会将其从原来的位置移动到新的位置

2.2 Node.prototype.hasChildNodes()

hasChildNodes方法返回一个布尔值,表示当前节点是否有子节点

let div = document.getElementById("box")
if(div.hasAttributes()){
    div.removeChild(div.childNodes[0])
}

如果div节点有子节点,那么就移出第一个子节点,子节点包括所有类型的节点,不仅仅是元素节点。只包含一个空格,hasChildNodes方法也会返回true

判断节点有没有子节点的方法

  • node.hasChildNodes()
  • node.firstChild !== null
  • node.childNodes && node.childNodes.length > 0

2.3 Node.prototype.cloneNode()

loneNode方法用于克隆一个节点 它接受一个布尔值作为参数,表示是否同时克隆子节点.它的返回值是一个克隆出来的新节点

let newDiv = document.querySelector('div').cloneNode(true);
  • 该方法返回的节点不在文档之中,即没有任何父节点,必须使用诸如Node.appendChild这样的方法添加到文档之中
  • 克隆一个节点,会拷贝该节点的所有属性,但会丢失事件方法

2.4 Node.prototype.insertBefore()

insertBefore方法用于将某个节点插入父节点内部的指定位置

接受两个参数

  • 第一个参数是所要插入的节点
  • 第二个参数是父节点内部的一个子节点
  • 新节点将插入到这个节点的前面,返回值是插入的新节点
var p = document.createElement('p');
document.body.insertBefore(p, document.body.firstChild);

新建一个节点,插在document.body.firstChild的前面,节点就成为document.body的第一个子节点。如果insertBefore方法的第二个参数为null,则新节点将插在当前节点内部的最后位置,变成最后一个子节点。

var p = document.createElement('p');
document.body.insertBefore(p, null);

2.5 Node.prototype.removeChild()

removeChild方法接受一个子节点作为参数,用于从当前节点移除该子节点。返回值是移除的子节点

var div = document.getElementById('box');
div.parentNode.removeChild(div);

注意,removeChild方法是在div父节点上调用的,不是在dib节点上调用的,如果参数节点不是当前节点的子节点,removeChild方法将报错。

2.6 Node.prototype.replaceChild()

replaceChild方法用于将一个新的节点,替换当前节点的某一个子节点

var replacedNode = parentNode.replaceChild(newChild, oldChild);
  • newChild是用来替换的新节点
  • oldChild是将要替换走的子节点
  • 返回值是被替换的节点oldChild。

2.7 Node.prototype.isEqualNode(),Node.prototype.isSameNode()

isEqualNode方法返回一个布尔值,用于检查两个节点是否相等,相等的节点指的是两个节点的类型,属性,子节点相同

var p1 = document.createElement('p');
var p2 = document.createElement('p');

p1.isEqualNode(p2) // true

isSameNode方法返回一个布尔值,表示两个节点是否为同一个节点

var p1 = document.createElement('p');
var p2 = document.createElement('p');

p1.isSameNode(p2) // false
p1.isSameNode(p1) // true

2.8 Node.prototype.normalize()

normalize方法用于清理当前节点内部的所有文本节点,它会去除空的文本节点,并且将响铃的文本节点合并成一个

 
var div = document.createElement('div');

div.appendChild(document.createTextNode('Part 1 '));
div.appendChild(document.createTextNode('Part 2 '));

div.childNodes.length // 2
div.normalize();
div.childNodes.length // 1

七、直接获取节点的几种方式

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>直接获取子节点</title>
        <script type="text/javascript">
            function fun1(){
                //根据id获取元素
                var element01 = document.getElementById('d1')
                //获取元素的文本属性
                console.log(element01.innerText)
            }
            
            function fun2(classname){
                //根据class属性获取元素
                var elements = document.getElementsByClassName(classname)
                for(var i=0;i<elements.length;i++){
                    console.log(elements[i].innerText)
                }
            }
            function fun3(){
                //根据标签名获取标签对象。多个属性放在数组中
                var elements = document.getElementsByTagName('input')
                for(var i=0;i<elements.length;i++){
                    console.log(elements[i])
                }
            }
            
            function fun4(){
                //根据name属性的值获取
                var elements = document.getElementsByName('hobby')
                for(var i=0;i<elements.length;i++){
                    console.log(elements[i])
                }
            }
        </script>
    </head>
    <body>
        <div id='d1' class="a">这是第一个div</div>
        <div id='d2' class="a">这是第二个div</div>
        <div id='d3' class="a">这是第三个div</div>
        <input id='i1' class="a" name='name1'/>
        <div id='d4' class="b" name='name1'>这是第四个div</div>
        <div id='d5' class="b">这是第五个div</div>
        爱好:
        <input type="checkbox" name="hobby"  value="1" />篮球
        <input type="checkbox" name="hobby"  value="2" />足球
        <input type="checkbox" name="hobby"  value="3" />羽毛球

        <hr />
        <input type="button" value="id值获取" onclick='fun1()' />
        <input type="button" value="class属性值获取" onclick='fun2("a")' />
        <input type="button" value="标签名获取" onclick='fun3()' />
        <input type="button" value="name属性值获取" onclick='fun4()' />
    </body>
</html>

八、操作节点属性

<!doctype html>
<html>

    <head>
        <meta charset="utf-8">
        <title></title>
        <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
        <link href="css/mui.css" rel="stylesheet" />
        <script type="text/javascript">
            function func1(){
                var element = document.getElementById('in1')
                /*
                //方式一: 获取: 节点.属性名 修改:节点.属性名=属性值
                console.log(element.type)
                console.log(element.value)
                //修改 属性的值
                element.type = 'button'
                element.value = '真的很好' */
                
                //方式二:
                console.log(element.getAttribute('type'))
                console.log(element.getAttribute('value'))
                
                element.setAttribute('type', 'button')
                element.setAttribute('value', '你好他好')
                
            }
        </script>
    </head>
    <body>
        <input type="text" id="in1" value="你好呀" />
        <hr >
        <input type="button" value="改变" onclick="func1()" />
    </body>
</html>

九、操作节点样式

通过style.css样式名和通过设置class属性两种方式实现

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title></title>
        <script type="text/javascript">
            function func1(){
                
                var node = document.getElementById('div1')
                
                //方式一:
                /* node.style.width = '200px'
                node.style.height = '200px'
                node.style.border = '10px solid royalblue' */
                
                //方式二:给节点添加一个class属性,值设置为a
                node.setAttribute('class','a' )
            }
        </script>
        <style type="text/css">
            #div1{
                width: 100px;
                height: 100px;
                border: 1px solid red;
            }
            
            .a{
                background-color: #6495ED;
                color: blanchedalmond;
                font-size: 50px;
            }
        </style>
    </head>
    <body>
        <div id="div1">
            你好呀
        </div>
        
        <input type="button" value="测试" onclick="func1()"/>
    </body>
</html>

十、操作标签文本

  • innerHtml 操作双标签中间的HTML
  • innerText 操作双标签中间的 Text
  • value 操作表单标签值
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title></title>
        <style type="text/css">
            #d1{
                border: #6495ED;
                width: 100px;
                height: 100px;
            }
        </style>
        <script type="text/javascript">
            function func01(){
                var node = document.getElementById('d1')
                //获取文字
                //console.log(node.innerHTML) //方式一:将文字信息 包含span标签,和缩进都获取回来了
                console.log(node.innerText) // 方式二 a 文字 b 只能获取文字信息 
                
                var element = document.getElementById('i1')
                console.log(element.value)
            }
            
            function func02(){
                var node = document.getElementById('d1')
                //方式一:
                // node.innerText = '<h1>竹杖芒鞋轻胜马</h1>'、
                //方式二:
                node.innerHTML = '<h1>竹杖芒鞋轻胜马</h1>'
                
                //修改内容
                var element = document.getElementById('i1')
                element.value = '无敌了' //修改input标签中value属性的值
            }
        </script>
    </head>
    <body>
        <div id="d1">
            a
            <span>文字</span>
            b
        </div>
        
        <input type="text" id="i1" value="暮霭程程楚天阔" />
        <input type="button" value="获取内容" onclick="func01()"/>
        <input type="button" value="修改内容" onclick="func02()"/>
    </body>
</html>

十一、增加和删除节点

  • 创建元素createElement()
  • 增加元素appendChild()
  • 删除元素removeChild()
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>增加删除</title>
        <style type="text/css">
            #d1{
                border: 1px solid #FF0000;
                width: 400px;
                height: 200px;
            }
        </style>
        <script type="text/javascript">
            function fun1(){
                var div01 = document.getElementById('d1');
                //创建 一个input标签
                var username = document.createElement('input')
                //给标签设置属性
                username.setAttribute('type', 'text');
                username.setAttribute('value', '请输入内容');
                
                //将创建好的input标签指定给div01
                div01.appendChild(username);
                
                //创建一个密码框
                var password = document.createElement('input')
                //设置属性
                password.setAttribute('type', 'password')
                password.setAttribute('value', '请输入密码')
                
                //将标签添加给div01
                div01.appendChild(password)
                
                //创建删除按钮
                var del = document.createElement('input')
                //设置属性
                del.setAttribute('type', 'button');
                del.setAttribute('value','删除')
                del.onclick = function f1(){
                    alert('即将删除')
                    //删除元素
                    div01.removeChild(username)
                    div01.removeChild(password)
                    div01.removeChild(del)
                    div01.removeChild(br)
                }
                //添加给div01
                div01.appendChild(del)
                
                //添加一个换行标签
                var br = document.createElement('br')
                div01.appendChild(br)
            }
        </script>
    </head>
    <body>
        <div id="d1">
            
        </div>
        <input type="button" value="增加" onclick="fun1()" />
    </body>
</html>

十一、案例练习

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title></title>
        <style type="text/css">
            #outerdiv{
                width: 200px;
                height: 200px;
                border: #6495ED;
                background-color: gray;
                text-align: center;
                margin-top: 200px;
                margin-left: 200px;
            }
            #outerdiv input{
                width: 50px;
                height: 50px;
                margin: 20px;
            }
        </style>
        <script type="text/javascript">
            function func2(){
                alert('嘿嘿嘿!!!')
            }
            
            function func1(){
                //获取元素
                var d = document.getElementById('outerdiv');
                //通过随机数设置宽和高
                var left = Math.floor(Math.random()*1000);
                var top = Math.floor(Math.random()*500);
                
                //修改元素的左边距、上边距
                d.style.marginTop = top + 'px';
                d.style.marginLeft = left + 'px';
            }
        </script>
    </head>
    <body>
        <div id="outerdiv">
            <h3>dou you love me?</h3>
            <input type="button" value="是" onclick="func2()"/>
            <input type="button" value="否" onmousemove="func1()"/>
        </div>
    </body>
</html>
posted @ 2021-12-09 17:48  酒剑仙*  阅读(87)  评论(0)    收藏  举报