前端基础进阶-JavaScript核心(DOM操作)

目录

目录

目标

1、DOM简介

1.1 什么是DOM

1.2 DOM树

2、获取元素

2.1 如何获取页面元素

2.2 根据ID获取

2.3 根据标签名获取

2.4 通过HTML5新增的方法获取

2.5 获取特殊元素(body,html)

获取body元素

获取html元素

3、事件基础

3.1 事件概述

3.3 执行事件的步骤

3.4 分析事件三要素

4、操作元素

4.1 改变元素内容

innerText 和 innerHTML的区别

4.2 常用元素的属性操作

案例:分时显示不同图片,显示不同问候语

4.3 表单元素的属性操作

仿京东显示密码

案例:循环精灵图背景

案例:显示隐藏文本框内容

4.7 H5自定义属性

5、节点操作

5.1 为什么学节点操作

5.2 节点概述

5.3 节点层级

案例:新浪下拉菜单

3、兄弟节点

5.4 创建节点

5.4 添加节点

案例:简单版发布留言案例

5.5 删除节点

案例:删除留言案例

5.6 复制节点(克隆节点)

案例:动态生成表格

5.8 三种动态创建元素区别(面试题)

6.DOM重点核心



目标

  • 能够说出什么是DOM
  • 能够获取页面元素
  • 能够给元素注册事件
  • 能够操作DOM元素的属性
  • 能够创建元素
  • 能够操作DOM节点

1、DOM简介

1.1 什么是DOM

 

文档对象模型(Document Object Model,简称DOM),是W3C组织推荐的处理可扩展标记语言(HTML或者XML)的标准编程接口

W3C已经定义了一系列的DOM接口,通过这些DOM接口可以改变网页的内容、结构和样式

 

1.2 DOM树

 

  • 文档:一个页面就是一个文档,DOM中使用document表示
  • 元素:页面中的所有标签都是元素,DOM中使用element表示
  • 节点:网页中的所有内容都是节点(标签、属性、文本、注释等),DOM中使用node表示

DOM把以上内容都看做是对象

 

 

2、获取元素

2.1 如何获取页面元素

 

DOM在我们实际开发中主要用来操作元素

我们如何来获取页面中的元素呢?

获取页面中的元素可以使用以下几种方式:

  • 根据ID获取
  • 根据标签名获取
  • 通过HTML5新增的方式获取
  • 特殊元素获取

 

getElementById()

注意:

  • 因为文档页面从上往下加载,所以先有标签,然后才能getElementById
  • 参数是字符串,所以需要加引号
  • 返回的是一个 element 对象

console.dir 可以打印返回的元素对象,更好的查看里面的属性和方法

 

getElementsByTagName()

  • 参数是字符串,所以需要加引号d
  • 得到的是对象的集合,可以用遍历来获取所有对象
  • 得到的是动态的 例子: 获取ol里面的li

 

getElementsByClassName()

类名选择器

 

querySelector()

HTML5新增的

返回指定选择器的第一个对象

 

querySelectorAll()

返回指定选择器的所有对象集合 用法和querySelector()一样

 

document.body

获取body元素

 

document.documentElement

获取html元素

 

2.2 根据ID获取

使用getElementById()方法可以获取带有ID的元素对象

Document的方法getElementById( )返回一个匹配特定ID的元素。由于元素的ID在大部分情况下要求是独一无二的,这个方法自然而然地成为了一个高效查找特定元素的方法。

如果需要查找到那些没有ID的元素.你可以考虑过CSS选择器使用querySelector( )。

 

 

 

 

2.3 根据标签名获取

使用getElementsByTagName()方法可以返回带有指定标签名的对象的集合

document.getElementsByTagName('标签名');

1.因为得到的是一个对象的集合,所以我们想要操作里面的元素就需要遍历·

2.得到元素对象是动态的

还可以获取某个元素(父元素)内部的所有指定标签名的子元素。

element.getElementsByTagName('标签名');

注意:父元素必须是单个对象(必须指明是哪一个元素对象),获取的时候不包括父元素自己。

<!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>

    <ul>

        <li>知否知否,应是等你好久11</li>
    
        <li>知否知否,应是等你好久11</li>
    
        <li>知否知否,应是等你好久11</li>

        <li>知否知否,应是等你好久11</li>

    </ul>

    <ol id="ol">

        <li>生僻字</li>

        <li>生僻字</li>

        <li>生僻字</li>

        <li>生僻字</li>

    </ol>

    <script>

        // 1.返回的是 获取过来元素对象的集合 以伪数组的形式存储的

        var lis = document.getElementsByTagName('li');

        console.log(lis);

        console.log(lis[0]);

        // 2. 我们想要依次打印里面的元素对象我们可以采取遍历的方式

        for (var i = 0; i < lis.length; i++) {

            console.log(lis[i]);

        }

        // 3. 如果页面中只有一个li 返回的还是伪数组的形式

        // 4. 如果页面中没有这个元素 返回的是空的伪数组的形式

        // 5. element.getElementsByTagName('标签名'); 父元素必须是指定的单个元素

        // var ol = document.getElementsByTagName('ol'); // [ol]
        
        // console.log(ol[0].getElementsByTagName('li'));

        var ol = document.getElementById('ol');

        console.log(ol.getElementsByTagName('li'));

    </script>

</body>

</html>

 

2.4 通过HTML5新增的方法获取

 

1. document.getElementsByClassName( 类名');     //根据类名返回元素对象集合

2. document.querySelegtor ( 选择器');     //根据指定选择器返回第一个元素对象

3. document . querySelectorAll( '选择器y);    //根据指定选择器返回

 

<body>

    <div class="box">盒子1</div>

    <div class="box">盒子2</div>

    <div id="nav">

        <ul>

                <li>首页</li>

                <li>产品</li>

        </ul>

    </div>

    <script>

        // 1. getElementsByClassName 根据类名获得某些元素集合

        var boxs = document.getElementsByClassName('box');

        console.log(boxs);

        // 2. querySelector 返回指定选择器的第一个元素对象  切记 里面的选择器需要加符号 .box  #nav

        var firstBox = document.querySelector('.box');

        console.log(firstBox);

        var nav = document.querySelector('#nav');

        console.log(nav);

        var li = document.querySelector('li');

        console.log(li);

        // 3. querySelectorAll()返回指定选择器的所有元素对象集合

        var allBox = document.querySelectorAll('.box');
                
        console.log(allBox);

        var lis = document.querySelectorAll('li');

        console.log(lis);

    </script>

</body>

 

2.5 获取特殊元素(body,html)

获取body元素

1. doucumnet.body      //返回body元素对象

 

获取html元素

1. document .documentElement    //返回html元素对象

 

<!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>

<script>

// 1.获取body 元素

var bodyEle = document.body;

console.log(bodyEle);

console.dir(bodyEle);

// 2.获取html 元素

// var htmlEle = document.html;

var htmlEle = document.documentElement;

console.log(htmlEle);

</script>

</body>

</html>

 

3、事件基础

3.1 事件概述

 

JavaScript使我们有能力创建动态页面,而事件是可以被JavaScript侦测到的行为。

简单理解:触发——响应机制。

网页中的每个元素都可以产生某些可以触发JavaScript的事件,例如,我们可以在用户点击某按钮时产生一个事件,然后去执行某些操作。

 

<body>

<button id="btn">唐伯虎</button>

<script>

// 点击一个按钮,弹出对话框

// 1. 事件是有三部分组成  事件源  事件类型  事件处理程序   我们也称为事件三要素

//(1) 事件源 事件被触发的对象   谁  按钮

var btn = document.getElementById('btn');

//(2) 事件类型  如何触发 什么事件 比如鼠标点击(onclick) 还是鼠标经过 还是键盘按下

//(3) 事件处理程序  通过一个函数赋值的方式 完成

btn.onclick = function() {

alert('点秋香');

}

</script>

</body>

 

3.3 执行事件的步骤

1、获取事件源

2、注册事件(绑定事件)

3、添加事件处理程序(采取函数赋值形式)

事件由三部分组成:

  • 事件源 事件被触发的对象 比如按钮
  • 事件类型 如何触发 比如鼠标点击、鼠标经过、键盘按下、滚动滚轮
  • 事件处理程序 通过函数赋值的方式完成

<body>

<div>123</div>

<script>

// 执行事件步骤

// 点击div 控制台输出 我被选中了

// 1. 获取事件源

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

// 2.绑定事件 注册事件

// div.onclick

// 3.添加事件处理程序

div.onclick = function() {

console.log('我被选中了');

}

</script>

</body>

 

事件都有:

鼠标事件

触发条件

onclick

鼠标点击左键触发

onmouseover

鼠标经过触发

onmouseout

鼠标离开触发

onfocus

获得鼠标焦点触发

onblur

失去鼠标焦点触发

onmousemove

鼠标移动触发

onmouseup

鼠标弹起触发

onmousedown

鼠标按下触发

 

 

3.4 分析事件三要素

下拉菜单三要素

关闭广告三要素

 

4、操作元素

JavaScript的DOM操作可以改变网页内容、结构和样式,我们可以利用DOM操作元素来改变元素里面的内容、属性等。注意以下都是属性

 

4.1 改变元素内容

element.innerText

  • 从起始位置到终止位置的内容,但它去除Html标签,同时空格和换行也会去掉
  • innerText不识别HTML标签
  • 可读写的,可以获取元素里面的内容

element.innerHTML

  • 从起始位置到终止位置的全部内容,包括Html标签,同时保留空格和换行
  • 能识别HTML标签
  • 可读写的,可以获取元素里面的内容

 

<!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>

<style>

div,

p {

width: 300px;

height: 30px;

line-height: 30px;

color: #fff;

background-color: pink;

}

</style>

</head>

<body>

<button>显示当前系统时间</button>

<div>某个时间</div>

<p>1123</p>

<script>

// 当我们点击了按钮,  div里面的文字会发生变化

// 1. 获取元素

var btn = document.querySelector('button');

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

// 2.注册事件

btn.onclick = function() {

// div.innerText = '2019-6-6';

div.innerText = getDate();

}

function getDate() {

var date = new Date();

// 我们写一个 2019年 5月 1日 星期三

var year = date.getFullYear();

var month = date.getMonth() + 1;

var dates = date.getDate();

var arr = ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'];

var day = date.getDay();

return '今天是:' + year + '' + month + '' + dates + '' + arr[day];

}

// 我们元素可以不用添加事件

var p = document.querySelector('p');

p.innerText = getDate();

</script>

</body>

</html>

 

innerText 和 innerHTML的区别

<body>

<div></div>

<p>

我是文字

<span>123</span>

</p>

<script>

// innerText 和 innerHTML的区别

// 1. innerText 不识别html标签 非标准  去除空格和换行

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

// div.innerText = '<strong>今天是</strong> 2019';

// 2. innerHTML 识别html标签 W3C标准 保留空格和换行的

div.innerHTML = '<strong>今天是:</strong> 2019';

// 这两个属性是可读写的  可以获取元素里面的内容

var p = document.querySelector('p');

console.log(p.innerText);

console.log(p.innerHTML);

</script>

</body>

 

4.2 常用元素的属性操作

1. innerText、 innerHTML改变元素内容

2. src、 href

3. id、alt、 title

 

<!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>

<style>

img {

width: 300px;

}

</style>

</head>

<body>

<button id="ldh">刘德华</button>

<button id="zxy">张学友</button> <br>

<img src="images/ldh.jpg" alt="" title="刘德华">

<script>

// 修改元素属性  src

// 1. 获取元素

var ldh = document.getElementById('ldh');

var zxy = document.getElementById('zxy');

var img = document.querySelector('img');

// 2. 注册事件  处理程序

zxy.onclick = function() {

img.src = 'images/zxy.jpg';

img.title = '张学友思密达';

}

ldh.onclick = function() {

img.src = 'images/ldh.jpg';

img.title = '刘德华';

}

</script>

</body>

</html>

 

案例:分时显示不同图片,显示不同问候语

根据不同时间,页面显示不同图片,同时显示不同的问候语。

如果上午时间打开页面,显示上午好,显示上午的图片。

如果下午时间打开页面,显示下午好,显示下午的图片。

如果晚上时间打开页面,显示晚上好,显示晚上的图片。

 

案例分析:

①根据系统不同时间来判断,所以需要用到日期内置对象

②利用多分支语句来设置不同的图片

③需要一个图片,并且根据时间修改图片,就需要用到操作元素src属性

④需要一个div元素,显示不同问候语,修改元素内容即可

 

<!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>

<style>

img {

width: 300px;

}

</style>

</head>

<body>

<img src="images/s.gif" alt="">

<div>上午好</div>

<script>

// 根据系统不同时间来判断,所以需要用到日期内置对象

// 利用多分支语句来设置不同的图片

// 需要一个图片,并且根据时间修改图片,就需要用到操作元素src属性

// 需要一个div元素,显示不同问候语,修改元素内容即可

// 1.获取元素

var img = document.querySelector('img');

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

// 2. 得到当前的小时数

var date = new Date();

var h = date.getHours();

// 3. 判断小时数改变图片和文字信息

if (h < 12) {

img.src = 'images/s.gif';

div.innerHTML = '亲,上午好,好好写代码';

} else if (h < 18) {

img.src = 'images/x.gif';

div.innerHTML = '亲,下午好,好好写代码';

} else {

img.src = 'images/w.gif';

div.innerHTML = '亲,晚上好,好好写代码';

}

</script>

</body>

</html>

 

 

4.3 表单元素的属性操作

 

利用DOM可以操作如下表单元素的属性:

type. value、checked、 selected、disabled

修改表单属性

disabled 让某个表单被禁用,不能被点击, 用法:

btn.onclick = function () {
    btn.disabled = true;
    //或者写成下面这种
    this.disabled = true;
    //this指向的是时间函数的调用者
}

 

<!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>

<button>按钮</button>

<input type="text" value="输入内容">

<script>

// 1. 获取元素

var btn = document.querySelector('button');

var input = document.querySelector('input');

// 2. 注册事件 处理程序

btn.onclick = function() {

// input.innerHTML = '点击了';  这个是 普通盒子 比如 div 标签里面的内容

// 表单里面的值 文字内容是通过 value 来修改的

input.value = '被点击了';

// 如果想要某个表单被禁用 不能再点击 disabled  我们想要这个按钮 button禁用

// btn.disabled = true;

this.disabled = true;

// this 指向的是事件函数的调用者 btn

}

</script>

</body>

</html>

 

仿京东显示密码

仿京东显示密码,点击按钮将密码框显示为文本框,并可以查看密码明文

案例分析:

核心思路︰利用样式的显示和隐藏完成,display.none隐藏元素display.block显示元素

点击按钮,就让这个二维码盒子隐藏起来即可

 

<!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>

<style>

.box {

position: relative;

width: 74px;

height: 88px;

border: 1px solid #ccc;

margin: 100px auto;

font-size: 12px;

text-align: center;

color: #f40;

/* display: block; */

}

.box img {

width: 60px;

margin-top: 5px;

}

.close-btn {

position: absolute;

top: -1px;

left: -16px;

width: 14px;

height: 14px;

border: 1px solid #ccc;

line-height: 14px;

font-family: Arial, Helvetica, sans-serif;

cursor: pointer;

}

</style>

</head>

<body>

<div class="box">

淘宝二维码

<img src="images/tao.png" alt="">

<i class="close-btn">×</i>

</div>

<script>

// 1. 获取元素

var btn = document.querySelector('.close-btn');

var box = document.querySelector('.box');

// 2.注册事件 程序处理

btn.onclick = function() {

box.style.display = 'none';

}

</script>

</body>

</html>

 

 

案例:循环精灵图背景

可以利用for循环设置一组元素的精灵图背景

案例分析:

首先精灵图图片排列有规律的

核心思路:利用for循环修改精灵图片的背景位置background-position

剩下的就是考验你的数学功底了

让循环里面的i索引号*44就是每个图片的y坐标

 

<!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>

<style>

* {

margin: 0;

padding: 0;

}

li {

list-style-type: none;

}
.box {

width: 250px;

margin: 100px auto;

}

.box li {

float: left;

width: 24px;

height: 24px;

background-color: pink;

margin: 15px;

background: url(images/sprite.png) no-repeat;

}

</style>

</head>

<body>

<div class="box">

<ul>

<li></li>

<li></li>

<li></li>

<li></li>

<li></li>

<li></li>

<li></li>

<li></li>

<li></li>

<li></li>

<li></li>

<li></li>

</ul>

</div>

<script>

// 1. 获取元素 所有的小li

var lis = document.querySelectorAll('li');

for (var i = 0; i < lis.length; i++) {

// 让索引号 乘以 44 就是每个li 的背景y坐标  index就是我们的y坐标

var index = i * 44;

lis[i].style.backgroundPosition = '0 -' + index + 'px';

}

</script>

</body>

</html>

 

案例:显示隐藏文本框内容

京东搜索框,默认是“手机”两个字,当用户点击搜索框的时候,“手机”两个字消失,当输入文本之后,保持文本内容不变

案例分析:

  • 如果获得焦点,判断里面是否是默认文字,如果是默认文字,就清空表单内容
  • 如果失去焦点,判断表单是否为空,如果为空,则表单内容改为默认文字
  • 获得焦点的时候,把文本框里的文字变黑
  • 失去焦点的时候,文本框文字变浅
  • 获得焦点 onfocus 失去焦点 onblur

案例分析

  • 一个大盒子,里面上下两个小盒子
  • 上面的模块,点击某一个之后,这个的背景色是红色,其余的是灰色(排他思想)
  • 点击某一个之后,显示这个模块对应的内容,其他的隐藏,这个要写到点击事件里面
  • 规律:下面的显示内容和上面的小 li 一一对应
  • 核心思路:
    • 给上面的tab_list 添加自定义属性,属性号从0开始
    • 当点击上面的模块,下面的队形的显示模块开始显示,其他的隐藏

 

<!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>

<style>

* {

margin: 0;

padding: 0;

}

li {

list-style-type: none;

}

.tab {

width: 978px;

margin: 100px auto;

}

.tab_list {

height: 39px;

border: 1px solid #ccc;

background-color: #f1f1f1;

}

.tab_list li {

float: left;

height: 39px;

line-height: 39px;

padding: 0 20px;

text-align: center;

cursor: pointer;

}

.tab_list .current {

background-color: #c81623;

color: #fff;

}

.item_info {

padding: 20px 0 0 20px;

}

.item {

display: none;

}

</style>

</head>

<body>

<div class="tab">

<div class="tab_list">

<ul>

<li class="current">商品介绍</li>

<li>规格与包装</li>

<li>售后保障</li>

<li>商品评价(50000)</li>

<li>手机社区</li>

</ul>

</div>

<div class="tab_con">

<div class="item" style="display: block;">

商品介绍模块内容

</div>

<div class="item">

规格与包装模块内容

</div>

<div class="item">

售后保障模块内容

</div>

<div class="item">

商品评价(50000)模块内容

</div>

<div class="item">

手机社区模块内容

</div>

</div>

</div>

<script>

// 获取元素

var tab_list = document.querySelector('.tab_list');

var lis = tab_list.querySelectorAll('li');

var items = document.querySelectorAll('.item');

// for循环绑定点击事件

for (var i = 0; i < lis.length; i++) {

// 开始给5个小li 设置索引号

lis[i].setAttribute('index', i);

lis[i].onclick = function() {

// 1. 上的模块选项卡,点击某一个,当前这一个底色会是红色,其余不变(排他思想) 修改类名的方式

// 干掉所有人 其余的li清除 class 这个类

for (var i = 0; i < lis.length; i++) {

lis[i].className = '';

}

// 留下我自己

this.className = 'current';

// 2. 下面的显示内容模块

var index = this.getAttribute('index');

console.log(index);

// 干掉所有人 让其余的item 这些div 隐藏

for (var i = 0; i < items.length; i++) {

items[i].style.display = 'none';

}

// 留下我自己 让对应的item 显示出来

items[index].style.display = 'block';

}

}

</script>

</body>

</html>

 

4.7 H5自定义属性

自定义属性目的︰是为了保存并使用数据。有些数据可以保存到页面中而不用保存到数据库中。

自定义属性获取是通过getAttribute ('属性′〉获取。

但是有些自定义属性很容易引起歧义,不容易判断是元素的内置属性还是自定义属性。

H5给我们新增了自定义属性︰

 

1.设置H5自定义属性

H5规定自定义属性data-开头做为属性名并且赋值。

比如<div data-index= "1” ></div>

或者使用JS设置

element.setAttribute( 'data-index,2)

但是有些自定义属性容易引以歧义,不容易判断是内置属性还是自定义属性,所以H5给我们新增了自定义属性 H5规定自定义属性以 “data-” 开头

 

2.获取H5自定义属性

  • 兼容性:element.getAttribute('data-index')
  • H5新增:element.dataset.index 或者 element.dataset[ 'index' ]   ie11才开始支持

 

<!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 getTime="20" data-index="2" data-list-name="andy"></div>

<script>

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

// console.log(div.getTime);

console.log(div.getAttribute('getTime'));

div.setAttribute('data-time', 20);

console.log(div.getAttribute('data-index'));

console.log(div.getAttribute('data-list-name'));

// h5新增的获取自定义属性的方法 它只能获取data-开头的

// dataset 是一个集合里面存放了所有以data开头的自定义属性

console.log(div.dataset);

console.log(div.dataset.index);

console.log(div.dataset['index']);

// 如果自定义属性里面有多个-链接的单词,我们获取的时候采取 驼峰命名法

console.log(div.dataset.listName);

console.log(div.dataset['listName']);

</script>

</body>

</html>

 

 

5、节点操作

5.1 为什么学节点操作

1利用DOM提供的方法获取元素 (逻辑性不强,繁琐)

  • document.getElementById()
  • document.getElementByTagName()
  • document.querySelector 等等

 

2、利用节点层级关系获取元素(简单、符合逻辑)

  • 利用父子兄的节点关系获取元素
  • 逻辑性强,但是兼容性差

 

5.2 节点概述

 

uploading.4e448015.gif转存失败重新上传取消uploading.4e448015.gif转存失败重新上传取消

一般的,节点至少由nodeType(节点类型)、 nodeName(节点名称)、 nodeValue(节点值)这三个基本属性。

  • 元素节点 nodeType 为1
  • 属性节点 nodeType 为2
  • 文本节点 nodeType 为3 (文本节点包括文字、空格、换行等等)

在实际开发中,节点操作主要操作的是元素节点。

 

5.3 节点层级

利用DOM树可以把节点划分为不同的层级关系,最常见的是父子兄层级关系

父级节点

node.parentNode

注意:得到的离元素最近的父级节点(亲爸爸),如果找不到就返回null

子级节点

parentNode.childNodes (标准)

返回包含指定节点的子节点的集合,该集合为即时更新的集合

注意:返回值里面包含的子节点包含元素节点、文本节点等等

所以用 nodeType 判断,用for循环遍历

如果只想要获得里面的元素节点,则需要专门处理。所以我们一般不提倡使用childNodes

 

parentNode.children (非标准)

是一个只读属性,返回所有的子元素节点。它只返回子元素节点,其余节点不返回(重点掌握)

得到所有的子元素节点,虽然是非标准的,但是得到了浏览器的支持,所以以后大量使用这个

 

parentNode.firstChild

返回第一个子节点,找不到返回null,不管是文本节点还是元素节点都能找到

 

parentNode.firstElementChild

返回第一个子元素节点,找不到返回null,只返回元素节点(IE9以上才支持)

 

parentNode.lastChild

返回最后一个子节点,找不到返回null,不管是文本节点还是元素节点都能找到

 

parentNode.lastElementChild

返回最后一个子元素节点,找不到返回null,只返回元素节点(IE9以上才支持)

 

实际开发中,firstchild和 lastchild包含其他节点,操作不方便,而firstElementchild和lastElementchild又有兼容性问题,那么我们如何获取第一个子元素节点或最后一个子元素节点呢?

解决方案:

1.如果想要第一个子元素节点,可以使用parentNode.children[0]

 

uploading.4e448015.gif转存失败重新上传取消uploading.4e448015.gif转存失败重新上传取消

 

案例:新浪下拉菜单

uploading.4e448015.gif转存失败重新上传取消uploading.4e448015.gif转存失败重新上传取消

分析:nav导航栏中有ul和li,li下面又有ul和li,第二层ul和li在鼠标移上去的时候才显示

  • 导航栏里面的li都要有鼠标经过的效果,所以需要循环注册
  • 核心原理:当鼠标经过li 的时候,孩子的ul 和li 显示,当鼠标离开,则隐藏

 

<!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>

<style>

* {

margin: 0;

padding: 0;

}

li {

list-style-type: none;

}

a {

text-decoration: none;

font-size: 14px;

}

.nav {

margin: 100px;

}

.nav>li {

position: relative;

float: left;

width: 80px;

height: 41px;

text-align: center;

}

.nav li a {

display: block;

width: 100%;

height: 100%;

line-height: 41px;

color: #333;

}

.nav>li>a:hover {

background-color: #eee;

}

.nav ul {

display: none;

position: absolute;

top: 41px;

left: 0;

width: 100%;

border-left: 1px solid #FECC5B;

border-right: 1px solid #FECC5B;

}

.nav ul li {

border-bottom: 1px solid #FECC5B;

}

.nav ul li a:hover {

background-color: #FFF5DA;

}

</style>

</head>

<body>

<ul class="nav">

<li>

<a href="#">微博</a>

<ul>

<li>

<a href="">私信</a>

</li>

<li>

<a href="">评论</a>

</li>

<li>

<a href="">@我</a>

</li>

</ul>

</li>

<li>

<a href="#">微博</a>

<ul>

<li>

<a href="">私信</a>

</li>

<li>

<a href="">评论</a>

</li>

<li>

<a href="">@我</a>

</li>

</ul>

</li>

<li>

<a href="#">微博</a>

<ul>

<li>

<a href="">私信</a>

</li>

<li>

<a href="">评论</a>

</li>

<li>

<a href="">@我</a>

</li>

</ul>

</li>

<li>

<a href="#">微博</a>

<ul>

<li>

<a href="">私信</a>

</li>

<li>

<a href="">评论</a>

</li>

<li>

<a href="">@我</a>

</li>

</ul>

</li>

</ul>

<script>

// 1. 获取元素

var nav = document.querySelector('.nav');

var lis = nav.children; // 得到4个小li

// 2.循环注册事件

for (var i = 0; i < lis.length; i++) {

lis[i].onmouseover = function() {

this.children[1].style.display = 'block';

}

lis[i].onmouseout = function() {

this.children[1].style.display = 'none';

}

}

</script>

</body>

</html>

 

3、兄弟节点

node.nextSibling 得到下一个兄弟节点,包括元素节点和文本节点

node.previousSibling 得到上一个兄弟节点,包括元素节点和文本节点

//下面两个方法只有IE9以上才能兼容

node.nextElementSibling 得到下一个兄弟元素节点,只有元素节点

node.previousElementSibling 得到上一个兄弟元素节点,只有元素节点

<!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>我是div</div>

<span>我是span</span>

<script>

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

// 1.nextSibling 下一个兄弟节点 包含元素节点或者 文本节点等等

console.log(div.nextSibling);

console.log(div.previousSibling);

// 2. nextElementSibling 得到下一个兄弟元素节点

console.log(div.nextElementSibling);

console.log(div.previousElementSibling);

</script>

</body>

</html>

 

 

uploading.4e448015.gif转存失败重新上传取消uploading.4e448015.gif转存失败重新上传取消

 

5.4 创建节点

document.createElement('tagName')

document.createElement()这个方法创建由tagName指定的 HTML 元素,因为这些元素原先不存在,是根据我们的需求动态生成的,所以也称为动态创建元素节点

 

5.4 添加节点

1. node .appendchild(child)

node.appendchild()方法将一个节点添加到指定父节点的子节点列表末尾。类似于css里面的after伪元素。

 

2. node.insertBefore(child,指定元素)

node.insertBefore ()方法将一个节点添加到父节点的指定子节点前面。类似于css里面的 before伪元素。

 

<!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>

<ul>

<li>123</li>

</ul>

<script>

// 1. 创建节点元素节点

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

// 2. 添加节点 node.appendChild(child)  node 父级  child 是子级 后面追加元素  类似于数组中的push

var ul = document.querySelector('ul');

ul.appendChild(li);

// 3. 添加节点 node.insertBefore(child, 指定元素);

var lili = document.createElement('li');

ul.insertBefore(lili, ul.children[0]);

// 4. 我们想要页面添加一个新的元素 : 1. 创建元素 2. 添加元素

</script>

</body>

</html>

 

案例:简单版发布留言案例

 

案例分析:

  • 页面组成:一个文本域,一个提交按钮,一个留言板
  • 当点击提交按钮的时候,先判断文本域内容是不是空,如果是空,就警告
  • 如果不是空,就新建一个li,然后把文本域的内容赋值给li,然后在ul里面的前面添加li

 

<!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>

<style>

* {

margin: 0;

padding: 0;

}

body {

padding: 100px;

}

textarea {

width: 200px;

height: 100px;

border: 1px solid pink;

outline: none;

resize: none;

}

ul {

margin-top: 50px;

}

li {

width: 300px;

padding: 5px;

background-color: rgb(245, 209, 243);

color: red;

font-size: 14px;

margin: 15px 0;

}

</style>

</head>

<body>

<textarea name="" id=""></textarea>

<button>发布</button>

<ul>

</ul>

<script>

// 1. 获取元素

var btn = document.querySelector('button');

var text = document.querySelector('textarea');

var ul = document.querySelector('ul');

// 2. 注册事件

btn.onclick = function() {

if (text.value == '') {

alert('您没有输入内容');

return false;

} else {

// console.log(text.value);

// (1) 创建元素

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

// 先有li 才能赋值

li.innerHTML = text.value;

// (2) 添加元素

// ul.appendChild(li);

ul.insertBefore(li, ul.children[0]);

}

}

</script>

</body>

</html>

 

5.5 删除节点

node.removeChild(child);

node.removeChild()从DOM中删除一个子节点,返回删除的节点

 

<!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>

<button>删除</button>

<ul>

<li>熊大</li>

<li>熊二</li>

<li>光头强</li>

</ul>

<script>

// 1.获取元素

var ul = document.querySelector('ul');

var btn = document.querySelector('button');

// 2. 删除元素  node.removeChild(child)

// ul.removeChild(ul.children[0]);

// 3. 点击按钮依次删除里面的孩子

btn.onclick = function() {

if (ul.children.length == 0) {

this.disabled = true;

} else {

ul.removeChild(ul.children[0]);

}

}

</script>

</body>

</html>

 

 

案例:删除留言案例

案例分析:

  • 在留言板案例的基础上添加功能
  • 当把文本域的内容幅值给 li 的时候,多添加一个删除的链接,
  • 循环把所有的链接获取过来,当我们点击一个链接的时候,删除当前链接所在的 li
  • 阻止链接跳转需要添加javascript:void(0);或者 javascript:;

<!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>

<style>

* {

margin: 0;

padding: 0;

}

body {

padding: 100px;

}

textarea {

width: 200px;

height: 100px;

border: 1px solid pink;

outline: none;

resize: none;

}

ul {

margin-top: 50px;

}

li {

width: 300px;

padding: 5px;

background-color: rgb(245, 209, 243);

color: red;

font-size: 14px;

margin: 15px 0;

}

li a {

float: right;

}

</style>

</head>

<body>

<textarea name="" id=""></textarea>

<button>发布</button>

<ul>

</ul>

<script>

// 1. 获取元素

var btn = document.querySelector('button');

var text = document.querySelector('textarea');

var ul = document.querySelector('ul');

// 2. 注册事件

btn.onclick = function() {

if (text.value == '') {

alert('您没有输入内容');

return false;

} else {

// console.log(text.value);

// (1) 创建元素

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

// 先有li 才能赋值

li.innerHTML = text.value + "<a href='javascript:;'>删除</a>";

// (2) 添加元素

// ul.appendChild(li);

ul.insertBefore(li, ul.children[0]);

// (3) 删除元素 删除的是当前链接的li  它的父亲

var as = document.querySelectorAll('a');

for (var i = 0; i < as.length; i++) {

as[i].onclick = function() {

// node.removeChild(child); 删除的是 li 当前a所在的li  this.parentNode;

ul.removeChild(this.parentNode);

}

}

}

}

</script>

</body>

</html>

 

5.6 复制节点(克隆节点)

node.cloneNode()

node.cloneNode() 方法返回调用该方法的节点的一个副本,也称为克隆节点/拷贝节点

注意:

  • 如果括号里面的参数为空或者为false,那么只是浅拷贝,即只复制节点本身,不克隆里面的子节点
  • 如果括号里面的参数为true,那么是深拷贝,复制标签并且复制里面的内容

 

<!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>

<ul>

<li>1111</li>

<li>2</li>

<li>3</li>

</ul>

<script>

var ul = document.querySelector('ul');

// 1. node.cloneNode(); 括号为空或者里面是false 浅拷贝 只复制标签不复制里面的内容

// 2. node.cloneNode(true); 括号为true 深拷贝 复制标签复制里面的内容

var lili = ul.children[0].cloneNode(true);

ul.appendChild(lili);

</script>

</body>

</html>

 

案例:动态生成表格

uploading.4e448015.gif转存失败重新上传取消uploading.4e448015.gif转存失败重新上传取消

案例分析

  1. 因为里面的学生数据都是动态的,我们需要js动态生成。这里我们模拟数据,自己定义好数据。数据我们采取对象形式存储。
  2. 所有的数据都是放到tbody里面的行里面。
  3. 因为行很多,我们需要循环创建多个行(对应多少人)
  4. 每个行里面又有很多单元格(对应里面的数据),我们还继续使用循环创建多个单元格,并且把数据存入里面(双重for循环)
  5. 最后一列单元格是删除,需要单独创建单元格。
    1. 因为里面的学生数据都是动态的,我们需要js动态生成。这里我们模拟数据,自己定义好
    2. 数据。数据我们采取对象形式存储。
    3. 所有的数据都是放到tbody里面的行里面。
    4. 因为行很多,我们需要循环创建多个行(对应多少人)

 

<!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>

<style>

table {

width: 500px;

margin: 100px auto;

border-collapse: collapse;

text-align: center;

}

td,

th {

border: 1px solid #333;

}

thead tr {

height: 40px;

background-color: #ccc;

}

</style>

</head>

<body>

<table cellspacing="0">

<thead>

<tr>

<th>姓名</th>

<th>科目</th>

<th>成绩</th>

<th>操作</th>

</tr>

</thead>

<tbody>

</tbody>

</table>

<script>

// 1.先去准备好学生的数据

var datas = [{

name: '魏璎珞',

subject: 'JavaScript',

score: 100

}, {

name: '弘历',

subject: 'JavaScript',

score: 98

}, {

name: '傅恒',

subject: 'JavaScript',

score: 99

}, {

name: '明玉',

subject: 'JavaScript',

score: 88

}, {

name: '大猪蹄子',

subject: 'JavaScript',

score: 0

}];

// 2. 往tbody 里面创建行: 有几个人(通过数组的长度)我们就创建几行

var tbody = document.querySelector('tbody');

for (var i = 0; i < datas.length; i++) { // 外面的for循环管行 tr

// 1. 创建 tr行

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

tbody.appendChild(tr);

// 2. 行里面创建单元格(跟数据有关系的3个单元格) td 单元格的数量取决于每个对象里面的属性个数  for循环遍历对象 datas[i]

for (var k in datas[i]) { // 里面的for循环管列 td

// 创建单元格

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

// 把对象里面的属性值 datas[i][k] 给 td 

// console.log(datas[i][k]);

td.innerHTML = datas[i][k];

tr.appendChild(td);

}

// 3. 创建有删除2个字的单元格

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

td.innerHTML = '<a href="javascript:;">删除 </a>';

tr.appendChild(td);

}

// 4. 删除操作 开始

var as = document.querySelectorAll('a');

for (var i = 0; i < as.length; i++) {

as[i].onclick = function() {

// 点击a 删除 当前a 所在的行(链接的爸爸的爸爸)  node.removeChild(child) 

tbody.removeChild(this.parentNode.parentNode)

}

}

// for(var k in obj) {

//     k 得到的是属性名

//     obj[k] 得到是属性值

// }

</script>

</body>

</html>

 

 

5.8 三种动态创建元素区别(面试题)

  • document.write()
    • 直接将内容写入页面的内容流,但是文档流执行完毕之后,他会导致页面全部重绘
  • document.innerHTML()
    • 将内容写入某个DOM节点,不会导致页面全部重绘
    • 拼接字符串的效率低
    • 创建多个元素效率更高,(不要拼接字符串,采取数组形式拼接),结构稍显复杂
  • document.createElement()
    • 创建多个元素效率稍低一点点,但是结构更清晰

总结:不同浏览器下,innerHTML比createElement效率高

 

<!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>

<button>点击</button>

<p>abc</p>

<div class="inner"></div>

<div class="create"></div>

<script>

// window.onload = function() {

//         document.write('<div>123</div>');

//     }

// 三种创建元素方式区别

// 1. document.write() 创建元素  如果页面文档流加载完毕,再调用这句话会导致页面重绘

// var btn = document.querySelector('button');

// btn.onclick = function() {

//     document.write('<div>123</div>');

// }

// 2. innerHTML 创建元素

var inner = document.querySelector('.inner');

// for (var i = 0; i <= 100; i++) {

//     inner.innerHTML += '<a href="#">百度</a>'

// }

var arr = [];for (var i = 0; i <= 100; i++) {

arr.push('<a href="#">百度</a>');

}

inner.innerHTML = arr.join('');

// 3. document.createElement() 创建元素

var create = document.querySelector('.create');

for (var i = 0; i <= 100; i++) {

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

create.appendChild(a);

}

</script>

</body>

</html>

 

 

innerHTML拼接效率测试

 

<!DOCTYPE html>

<html lang="en">

<head>

<meta charset="UTF-8">

<title>效率测试</title>

</head>

<body>

</body>

<script>

function fn() {

var d1 = +new Date();

var str = '';

for (var i = 0; i < 1000; i++) {

document.body.innerHTML += '<div style="width:100px; height:2px; border:1px solid blue;"></div>';

}

var d2 = +new Date();

console.log(d2 - d1);

}

fn();

</script>

</html>

 

innerHTML数组效率测试

 

<!DOCTYPE html>

<html lang="en">

<head>

<meta charset="UTF-8">

<title>效率测试</title>

</head>

<body>

</body>

<script>

function fn() {

var d1 = +new Date();

var array = [];

for (var i = 0; i < 1000; i++) {

array.push('<div style="width:100px; height:2px; border:1px solid blue;"></div>');

}

document.body.innerHTML = array.join('');

var d2 = +new Date();

console.log(d2 - d1);

}

fn();

</script>

</html>

 

createElement效率测试

 

<!DOCTYPE html>

<html lang="en">

<head>

<meta charset="UTF-8">

<title>效率测试</title>

</head>

<body>

</body>

<script>

function fn() {

var d1 = +new Date();

for (var i = 0; i < 1000; i++) {

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

div.style.width = '100px';

div.style.height = '2px';

div.style.border = '1px solid red';

document.body.appendChild(div);

}

var d2 = +new Date();

console.log(d2 - d1);

}

fn();

</script>

</html>

 

6.DOM重点核心

 

文档对象模型(Document Object Model,简称DOM ),是W3C组织推荐的处理可扩展标记语言( HTML或者XML )的标准编程接口。

w3C已经定义了一系列的DOM接口,通过这些DOM接口可以改变网页的内容、结构和样式.

1.对于JavaScript,为了能够使JavaScript操作HTMlL,JavaScript就有了一套自己的dom编程接口。

2.对于HTML,dom使得html形成一棵dom树.包含文档、元素、节点

 

我们获取过来的DOM元素是一个对象( object ),所以称为文档对象模型

 

关于dom操作,我们主要针对于元素的操作。主要有创建、增、删、改、查、属性操作、事件操作。

 

创建

1. document.write

2. innerHTML

3. createElement

 

  • appendChild
  • insertBefore

 

  • removeChild

 

修改DOM元素的属性,DOM元素的内容、属性、表单的值等

  • 修改元素属性:src、href、title等
  • 修改普通元素内容:innerHTML、innerText
  • 修改表单元素:value、type、disable等
  • 修改元素样式:style、className

 

  • 主要获取查询dom的元素
  • DOM提供的API方法:getElementById、getElementByTagName古老用法不太推荐
  • H5提供的新方法:querySelecter、querySelectorAll提倡使用
  • 利用节点操作获取元素:父(parentNode)、子(children)、兄(previousElementSibling、nextElementSibling)提倡使用

 

属性操作

主要针对于自定义属性

  • setAttribute : 设置DOM的属性
  • getAttribute : 得到DOM的属性
  • removeAttribute : 移除属性

 

事件操作

给元素注册事件,采取事件源.事件类型=事件处理程序

鼠标事件

触发条件

onclick

鼠标点击左键触发

onmouseover

鼠标经过触发

onmouseout

鼠标离开触发

onfocus

获得鼠标焦点触发

onblur

失去鼠标焦点触发

onmousemove

鼠标移动触发

onmouseup

鼠标弹起触发

onmousedown

鼠标按下触发

 

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值