js学习笔记——(10)DOM基础详解

一、DOM简介

1.什么是DOM
文档对象模型,是W3C组织推荐的处理可扩展标记语言(HTML和XMI)的标准编程接口。

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

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

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

二、获取元素

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

a.根据ID获取
使用getElementById()方法可以获取带有ID的元素对象。

<body>
	<div id="timer">2019-9-9</div>
	<script>
		//1.文档从上往下加载,js写在下面
		//2.get获得element元素by通过  驼峰命名法
		//3.参数  id 区分大小写
		//4.返回的是一个元素对象
		var timer = document.getElementById("timer");
		console.log(timer);
		console.log(typeof timer);
		//5.console.dir 打印我们返回的元素对象  更好的查看里面属性和方法
		console.dir(timer);
	</script>
</body>

b.根据标签名获取
getElementsByTagName()方法可以返回带有指定标签名的对象的集合

<body>
	<ul>
		<li>知否知否,应是等你好久!1</li>
		<li>知否知否,应是等你好久!2</li>
		<li>知否知否,应是等你好久!3</li>
		<li>知否知否,应是等你好久!4</li>
		<li>知否知否,应是等你好久!5</li>
	</ul>
	<ul id = "nav">
		<li>生僻字</li>
		<li>生僻字</li>
		<li>生僻字</li>
		<li>生僻字</li>
		<li>生僻字</li>
	</ul>
	<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.element.getElementsByTagName() 可以得到这个元素里面的某些
		var nav = document.getElementById('nav');
		var navLis = nav.getElementsByTagName('li');
		console.log(navLis);
	</script>
</body>

注意:
(1)因为得到的是一个对象的集合,所以我们操作里面元素就需要遍历。
(2)得到元素对象是动态的

c.通过HTML5新增的方法获取
1.getElementsByClassName(‘类名’);根据类名返回元素对象集合。
2.document.querySelector(‘选择器’);根据指定选择器返回第一个元素对象。
3.document.querySelectorAll(‘选择器’);根据指定选择器返回。

<body>
	<div class="box">盒子</div>
	<div class="box">盒子</div>
	<div id="nav">
		<ul>
			<li>首页</li>
			<li>产品</li>
		</ul>
	</div>
	<script>
		//1.getElementsByClassName 根据类名获得某些元素的1集合
		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>

d.特殊元素获取
获取body元素
document.body;
获取html元素
document.documentElement;

<body>
	<script>
		//1.获取body元素
		var bodyEle = document.body;
		console.log(bodyEle);
		console.dir(bodyEle);
		//2.获取html元素
		var htmlEle = document.documentElement;
		console.log(htmlEle);

	</script>

</body>

三、事件基础
1.事件概述
JavaScript使我们有能力创建动态页面,而事件是可以被JavaScript侦测到的行为。
简单理解:触发——响应机制。
网页中的每个元素都可以产生某些可以触发JavaScript的事件,例如,我们可以在用户点击某按钮时产生一个事件,然后去执行某些操作。
2.执行事件步骤
(1)获取事件源
(2)注册事件(绑定事件)
(3)添加事件处理机制(采取函数赋值形式)
3.常见的鼠标事件
在这里插入图片描述
四、操作元素
1.DOM操作可以改变网页内容、结构和样式,我们可以利用DOM元素来改变元素里面的内容、属性等。

2.改变元素内容

element.innerText

从起始到终止位置的内容,但它去除html标签,同时空格和换行也会去掉;

element.innerHTML

起始位置到终止位置的全部内容,包括html标签,同时保留空格和换行。

<body>
	<button id="dyz">第一张</button>
	<button id="dez">第二张</button><br>
	<img src='beauty_20200313143156.jpg'  title="这是第一张图片">
	<script>
		//修改元素属性
		//1.获取元素
		var dyz = document.getElementById('dyz');
		var dez = document.getElementById('dez');
		var img = document.querySelector('img');
		//2.注册事件  处理程序
		dez.onclick = function(){
			img.src = "beauty_20200313143213.jpg";
			img.title = "这是第二张图片";
		}
		dyz.onclick = function(){
			img.src = "beauty_20200313143156.jpg";
			img.title = "这是第一张图片";
		}
	</script>

</body>
<body>
	<img src="beauty_20200313143156.jpg">
	<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 = "beauty_20200313143156.jpg";
			div.innerHTML = '亲,上午好,好好写代码';
		} else if(h < 18){
			img.src = "beauty_20200313143213.jpg";
			div.innerHTML = '亲,下午好,好好写代码';
		}else {
			img.src = "IMG_20190930_204918.jpg";
			div.innerHTML = '亲,晚上好,好好写代码';
		}
	</script>
</body>

3.表单元素的属性操作

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

type、 value、 checked、 selected、 disabled、

<body>
	<button>按钮</button>
	<input type="text" name="" 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>

密码框案例:

<head>
	<meta charset="utf-8">
	<title></title>
	<style>
		.box{
			position: relative;
			width: 400px;
			border-bottom: 1px solid #ccc;
			margin: 100px auto;
		}
		.box input{
			width: 370px;
			height: 30px;
			border: 0;
			outline: none;
		}
		.box img{
			position: absolute;
			top: 2px;
			right: 2px;
			width: 24px;
		}
	</style>
</head>
<body>
	<div class="box">
		<label form="">
			<img src="close.png" id="eye">
		</label>
		<input type="password" name="" id="pwd">
		
	</div>
	<script>
		//1.获取元素
		var eye = document.getElementById('eye');
		var psw = document.getElementById('pwd');
		//2.注册事件  处理程序
		var flag = 0;
		eye.onclick = function(){
			if(flag == 0){
			pwd.type = 'text';
			flag = 1;  //赋值操作
			eye.src = 'open.png';
		}else {
			pwd.type = 'password';
			flag = 0;
			eye.src = 'close.png';
		}
		}
	</script>
</body>

4.样式属性操作
我们可以通过JS修改元素大小、颜色、位置等样式。

1.element.style 行内样式
2.element.className 类样式操作

注意:(1)JS里面的样式采取驼峰命名法,比如:fontSize、backgroundColor; (2)JS修改style样式操作,产生的是行内样式,css权重比较高

<style>
		div {
			width: 200px;
			height: 200px;
			background-color: pink;
		}
	</style>
</head>
<body>
	<div></div>
	<script>
		//1.获取元素
		var div = document.querySelector('div');
		//2.注册事件  处理程序
		div.onclick = function(){
			//div.style里面的属性  采取驼峰命名法
			this.style.backgroundColor = 'purple';
			this.style.width = '250px';
		}
	</script>
</body>
<style>
		.box{
			position: relative;
			width: 74px;
			height: 88px;
			border: 1px solid #ccc;
			margin: 100px auto;
			font-size: 12px;
			text-align: center;
			color: #f40;
		}
		.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,sana-serif;
			cursor: pointer;
		}
	</style>
</head>
<body>
	<div class="box">
		淘宝二维码
		<img src="code.png">
		<i class="close-btn">x</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>
<style>
		input{
			color: #999;
		}
	</style>
</head>
<body>
	<input type="text" name="" value="手机">
	<script>
		//1.获取元素
		var text = document.querySelector('input');
		//2.注册事件 获得焦点事件  onfocus
		text.onfocus = function(){
			// console.log('得到了焦点');
			if(this.value === '手机'){
				this.value = '';
			}
			//获得焦点  需要把文本框中的文字变黑
			this.style.color = '#333';
		}
		//3.注册事件 失去焦点事件  onblur
		text.onblur = function(){
			// console.log('失去了焦点');
			if(this.value === ''){
				this.value = '手机';
			}
			//失去焦点  颜色变浅
			this.style.color = '#999';
		} 
	</script>
</body>
<style>
		div{
			width: 150px;
			height: 150px;
			background-color: pink;
		}
		.change{
			background-color: purple;
			color: #fff;
			font-size: 25px;
			margin-top: 100px;
		}
	</style>
</head>
<body>
	<div>文本</div>
	<script>
		//1.使用element.style获得修改元素样式  如果样式比较少  或者功能简单的情况下使用
		var test = document.querySelector('div');
		test.onclick = function(){
			// this.style.backgroundColor = 'purple';
			// this.style.color = '#fff';
			// this.style.fontSize = '25px';
			// this.style.marginTop = '100px';
			//让我们当前元素的类名等于 change
			//2.我们可以通过修改元素 的className更改元素的样式  适用于样式较多或者功能更复杂的情况
			this.className = 'change';
		}
	</script>
</body>

注意:
(1)如果样式修改较多,可以采取操作类名方式更改元素样式;
(2)class因为是保留字,因此使用className来操作元素类名属性;
(3)className会直接更改元素的类名,会覆盖原先的类名。
5.自定义属性的操作

(1)获取属性值
element.属性; (获取属性值)
element.getAttribute(‘属性’) ;

区别:
element.属性; 获取内置属性值(元素本身自带的属性)
element.getAttribute(‘属性’); 主要获得自定义的属性(标准)我们程序员自定义的属性

(2)设置属性值
element.属性 = ‘值’; 设置内置属性
element.setAttribute(‘属性’,‘值’);

(3)移除属性
element.removeAttribute(‘属性’);

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

自定义属性获得通过getAttribute(‘属性’)获取;但是有些自定义属性很容易引起歧义,不容易判断是元素的内置属性还是自定义属性。H5给我们新增了自定义属性:

(1)设置H5自定义属性
H5规定自定义属性data-开头:
比如:

<div data-index = "1"></div>

或者使用JS设置

element.setAttribute('data-index', 2);

(2)获取H5自定义属性

1.兼容性获取:element.getAttribute(‘data-index’)
2.H5新增element.dataset.index 或者
element.dataset[‘index’] ie11以上

<body>
	<div getTime = "20" data-index = "2" data-list-name = "andy"></div>
	<script>
		var div = document.querySelector('div');
		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.listName);
		
	</script>
</body>

7.节点操作

a.获取元素通常使用两种方式:
(1)利用DOM提供的方法获取元素
document.getElementById()
document.getElementsByTagName()
document.querySelector()等,
缺点:繁琐、没有逻辑性
(2)利用节点层级关系获取元素
利用父子兄弟节点关系获取元素
逻辑性强,但是兼容性稍差

b.节点概述
一般地,节点至少拥有nodeType(节点类型)、nodeName(节点名称)和nodeValue(节点值)这三个基本属性。

元素节点nodeType为1

属性节点nodeType为2

文本节点nodeType为3(文本节点包含文字、空格、换行符)
实际开发中,节点操作主要操作的是元素节点

c.节点层级
常见的是父子兄层级关系

(1)父级节点

node.parentNode

(2)子节点

parentNode.childNodes(标准):拿到的是所有子节点, 包含元素节点 文本节点等等;实际开发中不提倡

parentNode.children(非标准):但是得到了各个浏览器的支持,因此可以放心使用

parentNode.firstChild:firstChild返回第一个子节点,找不到则返回null,同样,也是包含所有节点

parentNode.lastChild:返回最后一个子节点,找不到则返回null,同样,也是包含所有节点

parentNode.firstElementChild和parentNode.lastElementChild都返回的是元素节点,找不到则返回null, 这两个方法都有兼容性问题,IE9以上才支持。

<body>
	<ol>
		<li>我是li1</li>
		<li>我是li2</li>
		<li>我是li3</li>
		<li>我是li4</li>
	</ol>
	<script>
		var ol = document.querySelector('ol');
		//1.fistChild 获取的是第一个子节点  不管是文本节点还是元素节点
		console.log(ol.firstChild);
		console.log(ol.lastChild);
		//2.firstElementChild  返回第一个元素节点
		console.log(ol.firstElementChild);
		console.log(ol.lastElementChild);
		//3.实际开发的写法,既没有兼容性问题又返回第一个子元素
		console.log(ol.children[0]);
		console.log(ol.children[ol.children.length - 1]);
	</script>
</body>

(3)兄弟节点

node.nextSibling: 返回当前元素的下一个兄弟节点,找不到返回Null,同样包含所有节点

node.prexiousSibling:返回当前元素的上一个兄弟节点,找不到返回Null,同样包含所有节点

node.nextElementSibling: 返回当前元素的下一个兄弟元素节点,找不到返回Null

node.prexiousElementSibling:返回当前元素的上一个兄弟节点,找不到返回Null

node.nextElementSibling和node.prexiousElementSibling都存在兼容性问题,IE9以上才支持

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

解决方法:封装一个兼容性的函数;

function getNextElementSibling(element) {
            var el = element;
            while (el = el.nextElementSibling) {
                if (el.nodeType === 1) {
                    return el;
                }
            }
            return null}

(4)创建节点

document.createElement(‘tagName’)

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

(5)添加节点

node.appendChild(child)

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

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

简单留言发布:

<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8">
	<title></title>
	<style>
		textarea{
			width: 100px;
			height: 100px;
		}
		ul li{
			background-color: pink;
			width: 300px;
			margin-top: 5px;
		}
	</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.insertBefore(li,ul.children[0]);
			}
			
		}
	</script>
</body>
</html>

效果图:
在这里插入图片描述
(6)删除节点

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">
    <title>Document</title>
</head>

<body>
    <button>删除</button>
    <ul>
        <li>熊大</li>
        <li>熊二</li>
        <li>光头强</li>
    </ul>
</body>
<script>
    //1.获取元素
    var ul = document.querySelector('ul');
    var btn = document.querySelector('button');
    //2.删除元素
    // ul.removeChild(ul.children[0]);
    //3.点击按钮依次删除里面的子节点
    btn.onclick = function() {
        if (ul.children.length == 0) {
            this.disabled = true;
        } else {
            ul.removeChild(ul.children[0]);
        }

    }
</script>

</html>

(6)复制节点(克隆节点)

node.cloneNode()

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

注意:
1.如果括号里面参数为空或者false,则是浅拷贝,即只是克隆复制节点本身,不克隆里面的子节点(内容)。
2.如果括号里面为true,则是深拷贝,会复制节点本身及其里面的所有子节点

动态创建删除表格案例:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <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: 90
        }, {
            name: '王五',
            subject: 'javascript',
            score: 95
        }, {
            name: '王七',
            subject: 'javascript',
            score: 89
        }];
        //2.tbody中创建行:有几个人就创建几行,通过数组长度得到
        var tbody = document.querySelector('tbody');
        for (var i = 0; i < datas.length; i++) { //外面的for循环管行数
            //创建行
            var tr = document.createElement('tr');
            tbody.appendChild(tr);
            //行里面创建单元格 td  单元格数量取决于每个对象里面的属性个数
            //for循环遍历对象
            for (var k in datas[i]) { //里面的单元格管列数
                var td = document.createElement('td');
                //把对象里面的属性值给 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);
            }
        }
    </script>
</body>

</html>

五、三种动态创建元素的区别

  • documen.write()
  • document.innerHTML
  • document.createElement()

区别:

1.document.write是直接将内容写入页面流,但是文档流执行完毕,则它会导致页面重绘

2.innerHTML是将内容写入某个DOM节点,不会导致页面全部重绘

3.innerHTML创建多个元素效率更高(不要拼接字符串,采取数组形式拼接),结构稍微复

4.createElement()创建多个元素效率稍低一点点,但是结构清晰。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值