首页 > 技术文章 > javascrtpt DOM操作

Hybb 2019-10-28 23:21 原文

DOM

DOM:(document object mode)文档对象模型。DOM为文档提供了结构化表示,并定义了如何通过脚本来访问文档结构。

目的就是为了能让js操作html元素而制定的一个规范

DOM是由节点组成的:HTML加载完毕,渲染引擎会在内存中把HTML文档,生成一个DOM树

操作网页上的元素的API。比如让盒子移动、变色、轮播图等。

上图可知,在HTML当中,一切都是节点:(非常重要)

  • 元素节点:HTML标签。
  • 文本节点:标签中的文字(比如标签之间的空格、换行)
  • 属性节点::标签的属性。

整个html文档就是一个文档节点。所有的节点都是Object。

object节点维护的内容

img

dom操作的内容

节点查找

直接查找

根据ID查找

永远只会找到一个标签

// obj  = document.getElementById('元素的id') 永远只会找到一个标签
var dar = document.getElementById('d1');
console.log(dar)

根据类名查找

永远得到一个数组

var objs = document.getElementsByClassName('foo');
console.log(objs[0]);
console.log(objs[1]);

根据标签查找

永远得到一个数组

var objs = document.getElementsByTagName('div');
console.log(objs[0])
console.log(objs[1])
console.log(objs[2])

间接查找

节点之间的关系是以属性的方式存在的

找父亲

var p_obj = document.getElementsByClassName('foo')[0]
console.log(p_obj.parentElement);

找儿子

var objs = document.getElementById('d1');
console.log(objs.children);  // objs的子标签
console.log(objs.firstElementChild);  // objs的第一个子标签
console.log(objs.lastElementChild);  // objs的最后一个子标签

找哥哥

var p_obj = document.getElementsByClassName('foo')[0];
dac = p_obj.nextElementSibling   // p_obj的下一个同级元素
console.log(dac.previousElementSibling); // dac的上一个同级元素

找弟弟

var p_obj = document.getElementsByClassName('foo')[0];
console.log(p_obj.nextElementSibling);  // p_obj的下一个同级元素

操作节点

// 创建节点
	obj = document.createElement('p')
	<p></p>
	obj.innderText = 'p标签'
	<p>p标签</p>
// 添加节点
	父节点.appendChild(子节点对象)
	父节点.insertBefore(要添加的子对象,参考节点对象)
// 删除节点
	父节点.removeChild(子节点对象)
// 克隆节点
	节点.cloneNode()   只拷贝一层
	节点.cloneNode(True) 拷贝所有子节点
// 替换节点
	父节点.replaceChild(新对象,旧子节点)

创建标签

obj = document.createElement('p');  // 创建一个p标签

obj.innerText = '我是一个p标签'; // 给创建的p标签插入值

插入节点

  • appendChild 在查找到的元素最后一个元素的位置追加
  • insertBefore 在查找到的元素前插入
// appendChild
var p = document.createElement('p');
p.innerText = '我是一个p标签'
var obj = document.getElementById('d1');
obj.appendChild(p); // 将p标签插入到obj子标签的最后位置

// insertBefore
var p = document.createElement('p');
p.innerText = '我是一个p标签'
var obj = document.getElementById('d1');
var p2 = obj.firstElementChild;

obj.insertBefore(p,p2); // 将p标签插入到p2标签前

删除子节点

var obj = document.getElementById('d1');
// var las_obj = obj.lastElementChild;
var las_obj = document.getElementsByTagName('a')[0];
obj.removeChild(las_obj);  // 父节点 删除  las_obj

删除自己

var a_obj = document.getElementsByTagName('a')[0];
var di_obj = a_obj.parentElement;
di_obj.removeChild(a_obj);

复制节点

var obj = document.getElementById('d1');
var new_obj = obj.cloneNode(true);  
// 不加true 默认只会浅拷贝,例如只会拷贝匹配到的这一行,而不会拷贝这一行的子元素
obj.appendChild(new_obj);

替换节点

var new_p = document.createElement('p');
new_p.innerText = '我是一个新的p标签'
var obj = document.getElementById('d1');
var p_obj = obj.firstElementChild;
// 父节点.replaceChild(新节点,旧节点)
obj.replaceChild(new_p,p_obj);  

操作节点内的文本

// innerText pobj.innerText = '<a>我是一个a标签</a>'
// innerText 只人文本 html是不认识的
var new_p = document.createElement('p');
new_p.innerText = '<p>我是一个新的p标签</p>'  
console.log(new_p);

// innerHTML
var new_p = document.createElement('p');
new_p.innerHTML = '<a href="http://www.baidu.com">chaojibaidu</a>'
console.log(new_p);

操作值

var obj = document.getElementsByTagName('input')[0];
obj.value;  // 获取值
"alexvalue"

obj.value = 'cccc';  // 设置值

操作属性

// obj.setAttribute('属性名','属性值')
// obj.getAttribute('属性名')
// obj.removeAttribute('属性名')

var obj = document.getElementById('mi');
// 设置属性
obj.setAttribute('href','http://www.baidu.com')

// 删除属性
obj.removeAttribute('href')

// 获取属性的值
console.log(obj.getAttribute('href'));

操作类

// LOW方法
document.getElementsByTagName('li')[1].setAttribute('class','c_li');

var obj = document.getElementById('mi');
// 查看类的数组
obj.classList;

// 类名的数组中追加
obj.classList.add('c_li2');

// 类名数组中删除
obj.classList.remove('c_li');

// 类名数组中是否存在 存在返回true 不存在返回false
obj.classList.contains('c_li');
true

// 类名数组中存在就删除,没有就加上
obj.classList.toggle('c_li');
true
obj.classList.toggle('c_li');
false

操作样式

// obj.style.样式名 = 样式值
var obj = document.getElementById('mi');
obj.style.backgroundColor = 'red';
"red"

例子:红绿灯

<!DOCTYPE html>
<html lang="zh_CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Green</title>
    <style>
        .outer{
            border:solid darkgrey 5px;
            display:inline-block;
            padding:5px;
            border-radius:10px;
        }

        .light{
            float:left;
            height:100px;
            width:100px;
            border-radius:50%;
            background-color:lightgray;
            margin-left:5px;
        }

        .clearfix:after{
            content:'';
            clear:both;
            display: inline-block;
        }

        .red{
            background-color:red;
        }

        .yellow{
            background-color:yellow;
        }

        .green{
            background-color:green;
        }

    </style>
</head>
<body>
    <div class="outer"> 
        <div class="container">
            <div class="light red"></div>
            <div class="light"></div>
            <div class="light"></div>
        </div>
    </div>
</body>
<script>
    function fn(){
        var lights = document.getElementsByClassName('light');
        if (lights[0].classList.contains('red')){
            lights[0].classList.remove('red');
            lights[1].classList.add('yellow');
        }else if (lights[1].classList.contains('yellow')){
            lights[1].classList.remove('yellow');
            lights[2].classList.add('green');
        }else{
            lights[2].classList.remove('green');
            lights[0].classList.add('red');
        }
    }

    setInterval(fn,1000)
</script>
</html>

事件

JS是以事件驱动为核心的一门语言。

事件源:引发后续事件的html标签。
事件:js已经定义好了(见下图)
事件驱动程序:对样式和html的操作。也就是DOM。

代码书写步骤如下:(重要)

(1)获取事件源:document.getElementById(“box”); //类似与ios语言的 UIButton *adBtn = [UIButton buttonWithType:UIButtonTypeCustom];
(2)绑定事件: 事件源box.事件onclick = function(){ 事件驱动程序 };
(3)书写事件驱动程序:关于DOM的操作

代码示例:

<body>
<div id="box1"></div>

<script type="text/javascript">
    // 1、获取事件源
    var div = document.getElementById("box1");
    // 2、绑定事件
    div.onclick = function () {
        // 3、书写事件驱动程序
        alert("我是弹出的内容");
    }
</script>
</body>

常见事件如下:

img

3中绑定事件的方式:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
    <div>
        <ul id="items">
            <li>item1</li>
            <li>item2</li>
            <li>item3</li>
        </ul>
    </div>

    <button onclick="fn()">按钮1</button>
    <button id="bt2">按钮2</button>
    <button id="bt3">按钮3</button>
    <!-- <bottom>按钮1</bottom> -->
</body>

<script>

    var btn2 = document.getElementById('bt2');
    btn2.onclick = fn;


    function fn(){
        var obj = document.getElementById('items');
        var liobj = document.createElement('li');
        liobj.innerText = '插入的li标签'
        obj.appendChild(liobj);
    }

    var bt3 = document.getElementById('bt3');
    bt3.onclick =  function fn() {
            var obj = document.getElementById('items');
            var liobj = document.createElement('li');
            liobj.innerText = '插入的li标签'
            obj.appendChild(liobj);
        }

</script>
</html>

下面针对事件的三要素,进行分别介绍。

1、获取事件源(DOM节点的获取)

示例:

1.模态框案例

需求:打开网页时有一个普通的按钮,点击当前按钮显示一个背景图,中心并弹出一个弹出框,点击X的时候会关闭当前的模态框

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title></title>
        <style type="text/css">
            *{
                padding: 0;
                margin: 0;
            }
            html,body{
                height: 100%;
            }
            #box{
                width: 100%;
                height: 100%;
                background: rgba(0,0,0,.3);
            }
            #content{
                position: relative;
                top: 150px;
                width: 400px;
                height: 200px;
                line-height: 200px;
                text-align: center;
                color: red;
                background-color: #fff;
                margin: auto;
            }
            #span1{
                position: absolute;
                background-color: red;
                top: 0;
                right: 0;
                width: 30px;
                height: 30px;
                line-height: 30px;
                text-align: center;
                color: #fff;

            }
        </style>
    </head>
    <body>
        <button id="btn">弹出</button>
    </body>
    <script type="text/javascript">
        //获取dom元素 1.获取事件源
        var oBtn = document.getElementById('btn');
        //创建弹出模态框的相关DOM对象
        var oDiv = document.createElement('div');
        var oP = document.createElement('p');
        var oSpan = document.createElement('span');
        
        
        // 设置属性
        oDiv.id = 'box';
        oP.id = 'content'
        oP.innerHTML = '模态框成功弹出'
        oSpan.innerHTML = 'X';
        oSpan.id = 'span1'
        
        // 追加元素
        oDiv.appendChild(oP);
        oP.appendChild(oSpan);

        // 点击弹出按钮 弹出模态框
        oBtn.onclick = function(){
            //动态的添加到body中一个div
            this.parentNode.insertBefore(oDiv,oBtn)
            
        }
        // 点击X 关闭模态框
        oSpan.onclick = function(){
            // 移除oDiv元素
            oDiv.parentNode.removeChild(oDiv)
        }   
        
    </script>
</html>

2.Select选择框

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
<select name="province" id="province">
  <option value="0" selected>请选择省</option>
</select>
<select name="city" id="city">
  <option>请选择市:</option>
</select>
</body>
<script>
    data = {"河北": ["廊坊", "邯郸"], "北京": ["朝阳区", "海淀区"], "山东": ["威海市", "烟台市"]}
    var select1 =document.getElementById('province')
    for(i in data){
        var option = document.createElement('option')
        option.innerText = i
        select1.appendChild(option)
    }
    select1.onchange = function () {
        var select2 =document.getElementById('city')
        select2.innerText = null
        var choosed = select1.options[this.options.selectedIndex].innerText
        for(var i=0;i<data[choosed].length;i++){
            var option = document.createElement('option')
            option.value = i
            option.innerText = data[choosed][i]
            select2.appendChild(option)
        }
    }
</script>
</html>

3.Tab选项卡

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title></title>
        <style type="text/css">
            *{
                padding: 0;
                margin: 0;
            }
            ul{
                list-style: none;
            }
            #tab{
                width: 480px;
                margin: 20px auto;
                border: 1px solid red;
            }
            ul{
                width: 100%;
                overflow: hidden;
            }
            ul li{
                float: left;
                width: 160px;
                height: 60px;
                line-height: 60px;
                text-align: center;
                background-color: #cccccc;
            }
            
            ul li a{
                text-decoration: none;
                color:black;
            }
            li.active{
                background-color: red;
            }
            p{
                display: none;
                height: 200px;
                text-align: center;
                line-height: 200px;
                background-color: red;
            }
            p.active{
                display: block;
                
            }
            
        </style>
    </head>
    <body>
        <div id="tab">
            <ul>
                <li class="active">
                    <a href="#">首页</a>
                </li>
                <li>
                    <a href="#">新闻</a>
                </li>
                <li>
                    <a href="#">图片</a>
                </li>        
            </ul>
            <p class="active">首页内容</p>
            <p>新闻内容</p>
            <p>图片内容</p>
            
            
        </div>
    </body>
    <script type="text/javascript">
        window.onload = function(){
            // //需求:鼠标放到上面的li上,li本身变色(添加类),对应的p也显示出来(添加类);
                    //思路:1.点亮上面的盒子。   2.利用索引值显示下面的盒子。

            var tabli = document.getElementsByTagName('li');
            var tabContent = document.getElementsByTagName('p')
        
            for(var i = 0; i < tabli.length; i++){
                // 绑定索引值(新增一个自定义属性:index属性)
                tabli[i].index  = i;
                tabli[i].onclick = function(){
                    
                    // 1.点亮上面的盒子。   2.利用索引值显示下面的盒子。(排他思想)
                    for(var j = 0; j < tabli.length; j++){
                        tabli[j].className = '';
                        tabContent[j].className = '';
                    }    
                    this.className = 'active'
                    
                    tabContent[this.index].className = 'active';//【重要代码】
                }
        }
        }
        
    </script>
</html>

4.简易留言板

需求:当在textarea中输入内容,点击留言按钮,会添加到浏览器中,效果图如下:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>留言板</title>
        <style type="text/css">
            *{
                padding: 0;
                margin: 0;
            }
            .close{
                display: inline-block;
                width: 20px;
                height: 20px;
                line-height: 20px;
                text-align: center;
                cursor: pointer;
                background-color: rgba(0,0,0,.1);
                margin-left: 20px;
            }
        </style>
    </head>
    <body>
        <h1>简易留言板</h1>
        <div id="box">
            <!--<ul>
                
            </ul>-->
            
        </div>
        <textarea id="msg"></textarea>
        <input type="button" id="btn" value="留言"/>
        <button onclick="sum()">统计</button>
    </body>
    <script type="text/javascript">

        // 0 将ul标签添加到div#box标签中
        var oUl = document.createElement('ul');
        var oBox = document.getElementById('box');
        oBox.appendChild(oUl);
        
        var oBtn = document.getElementById('btn');
        var oMsg = document.getElementById('msg')
        // 控制留言的总数量
        var count = 0;
        oBtn.onclick = function(){
            
            
            // 点击留言按钮事件操作
            // 1.创建li标签
            var oLi = document.createElement('li');        
            //2.设置内容
            oLi.innerHTML = oMsg.value + "<span class='close'>X</span>"
            
            // 3.如果想在插入的第一个li获取的前面继续添加li标签
            //3.1获取li标签
            var olis = document.getElementsByTagName('li');
             //3.2 如果是第一次添加的li标签,则直接添加到ul的后面
            if(olis.length == 0){
                oUl.appendChild(oLi);
                count++;
                
            }else{
                // 3.3 如果不是第一次添加的li标签,则插入到第一个li标签的前面
                oUl.insertBefore(oLi,olis[0]);
                count++;
            }
            // 4.添加完成之后 清空textarea的值
            oMsg.value = '';
            
            
            // 5.点击X的时候删除当前的一条数据
            //5.1先获取所有的X
            var oSpans = document.getElementsByTagName('span');
            
            // 5.2for循环 对所有的X添加点击事件
            for(var i = 0; i< oSpans.length; i++){
                oSpans[i].onclick  = function(){
                    // 5.3 移除当前的li标签
                    oUl.removeChild(this.parentNode)
                    count--;
                }
            }
        
            
        }
    
        function sum(){
            alert('一共发布了'+count+'条留言');
            
        }
    </script>
</html>

推荐阅读