基础知识 | DOM

DOM简介

DOM :Document Object Model

          专门操作网页内容的一套现成的对象和函数的集合

          只有dom能操作,  jquery是基于dom封装的

          Dom标准,w3c指定并负责维护的一套对象和函数的标准,绝大多数浏览器都兼容

Dom4步 非常重要 (dom增删改查+事件绑定)

            查找触发事件的元素   必不可少

            绑定事件处理函数

                     元素.on 事件名=function(){}

           查找要修改的元素

          修改元素

Dom树

       内存中,保存整个网页内容的树形结构

      上下级关系,都适合用Dom树

       比如,一个html页面也是一个Dom树,其中标签自带的属性是那个标签的同级,标签之间的内容是标签的下级

:

直接获取元素

console.log 输出当前根节点以下所有元素

console.dir 输出当前节点的所有属性方法

根节点对象 document

document 根节点对象 代表整个dom树和所有网页内容

     案列:  直接输出根节点下所有元素

                         

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		<h1>标题一</h1>
		<span id="cute">可爱</span>
		<script>
		//输出节点及其子节点的dom树结构
		console.log(document);
		//输出当前子节点对象自己的属性和方法	
	    console.dir(document);
		</script>
	</body>
</html>

 document.documentElement  直接输出html下所有元素

 也就是说以html为根节点

 案列:  document.documentElement                   

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		<h1>标题一</h1>
		<span id="cute">可爱</span>
		<script>
		//输出节点及其子节点的dom树结构
		console.log(document.documentElement);
		//输出当前子节点对象自己的属性和方法
		console.dir(document.documentElement);
		</script>
	</body>
</html>

  document.head   直接输出head下所有元素

    也就是说以head为根节点

案列:document.head

上面例子的图没有展开的话也是这样的

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		<h1>标题一</h1>
		<span id="cute">可爱</span>
		<script>
		//输出节点及其子节点的dom树结构
		console.log(document.head);
		//输出当前子节点对象自己的属性和方法
		console.dir(document.head);
		</script>
	</body>
</html>

document.body   直接输出body下所有元素

 也就是以body为根节点

案列:document.body

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		<h1>标题一</h1>
		<span id="cute">可爱</span>
		<script>
		console.log(document.body);
		console.dir(document.body);
		</script>
	</body>
</html>

查找元素

节点树------不推荐使用

按节点关系查找元素

包含所有网页内容的树结构

包括两大类关系,6个属性,按关系可以分为父子关系 兄弟关系

连看不见的换行和空字符也被当做节点对象

父子关系

获取一个元素的父节点 元素.parentNode           //返回一个节点对象

获取一个元素的所有直接子节点 元素.childNodes   //返回一个包含多个直接子节点对象的类数组对象

获取一个元素下第一个直接子节点 元素.firstChild

获取一个元素下最后一个直接子节点 元素.lastChild

dom的下标也是从0开始

案列:获取sapn

目标获取span,一般来说下标是1,但是通过打印全部节点可知,下标为3

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		<h1>标题一</h1>
		<span id="cute">可爱</span>
		<script>
		// 目标:获取span
		console.log(document.body.childNodes[1]);//但结果是<h1>...,不是span
		
		//打印出所有body下子节点
		console.log(document.body.childNodes);
		
		//这样才能找出span
		console.log(document.body.childNodes[3]);
		</script>
	</body>
</html>

  兄弟关系

     获得一个元素相邻的前一个兄弟节点 元素.previousSibling

     获取一个元素相邻的下一个兄弟节点 元素.nextSibling

按元素树查找-------推荐使用

不会受看不见的空字符干扰

包括两大类关系,6个属性,按关系可以分为父子关系 兄弟关系

父子关系

获取一个元素的父元素      元素.parentElement           //返回一个元素对象

获取一个元素的所有直接子元素     元素.children       //返回一个包含多个直接子元素对象的类数组对象

获取一个元素下第一个直接子元素       元素.firstElementChild

获取一个元素下最后一个直接子元素     元素.lastElementChild

dom的下标也是从0开始

案列:获取body的子元素span

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		<h1>标题一</h1>
		<span id="cute">可爱</span>
		<script>
		// 目标:获取span
		console.log(document.body.children[1]);
		</script>
	</body>
</html>

 兄弟关系

 获得一个元素相邻的前一个兄弟元素 元素.previousElementSibling

 获取一个元素相邻的下一个兄弟元素 元素.nextElementSibling

按HTML特征查找

通过id名查找一个元素对象getElementById

var 元素对象=document.getElementById("id名");

找到,返回一个元素对象,找不到,返回

案例:查找id为nav的元素

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		<span>Hello World</span>
		<ul id="nav"> 
			<li>电影</li>
			<li>综艺
				<ul>
					<li>跑男</li>
					<li>爸爸</li>
					<li>极限</li>
				</ul>
			</li>
			<li>剧集</li>
		</ul>
		<script>
		//查找id为nav的元素
		var nav=document.getElementById("nav");
		console.log(nav);
		</script>
	</body>
</html>

 通过标签名(tagname)查找多个元素getElementsByTagName

<h1> </h1>这种 ,它会查询所有后代

var 类数组对象=任意父元素.getElementsByTagName("标签名");

找到,返回一个类数组对象,找不到返回一个空类数组对象{length:0} ,{length:0}  表示有一个对象,但里面没有东西

如果想要获取一个仅有的元素对象,需要加上[0],从类数组对象中0位置,取出唯一找到的一个元素对象

案例:查找nav下的所有li元素

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		<span>Hello World</span>
		<ul id="nav"> 
			<li>电影</li>
			<li>综艺
				<ul>
					<li>跑男</li>
					<li>爸爸</li>
					<li>极限</li>
				</ul>
			</li>
			<li>剧集</li>
		</ul>
		<script>
		//查找nav下的所有li元素
		var lis=nav.getElementsByTagName("li");
		console.log(lis);
		</script>
	</body>
</html>

案列:类数组对象[0]

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		<span>Hello World</span>
		<ul id="nav"> 
			<li>电影</li>
			<li>综艺
				<ul>
					<li>跑男</li>
					<li>爸爸</li>
					<li>极限</li>
				</ul>
			</li>
			<li>剧集</li>
		</ul>
		<script>
		//查找span
		//这个是集合
		var span=document.getElementsByTagName("span");
		console.log(span);
		
		//这个是元素
		var span2=document.getElementsByTagName("span")[0];
		console.log(span2);
		</script>
	</body>
</html>

通过类名查找多个元素getElementsByClassName

它会查询所有后代

var 类数组对象=任意父元素.getElementsByClassName("class名");

找到,返回一个类数组对象,包含指定标签名的元素对象,找不到返回一个空类数组对象{length:0}

如果想要获取一个仅有的元素对象,需要加上[0],从类数组对象中0位置,取出唯一找到的一个元素对象

如果一个元素被多个class修饰,只需要使用其中任意一个class,就可以找到这个元素

案列:类名查找元素


 

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		<span>Hello World</span>
		<span>可爱</span>
		<ul id="nav"> 
			<li class="item">电影</li>
			<li class="item">综艺
				<ul>
					<li class="item active">跑男</li>
					<li class="item">爸爸</li>
					<li class="item">极限</li>
				</ul>
			</li>
			<li class="item">剧集</li>
		</ul>
		<script>
		//查找class为item的所有元素
		var items=nav.getElementsByClassName("item");
		console.log(items);
		
		//查找class为active的单个元素
		var active=nav.getElementsByClassName("active")[0];
		console.log(active);
		</script>
	</body>
</html>

通过name名查找多个表单元素getElementsByName

var 类数组对象=document.getElementsByName("name名");

找到返回一个类数组对象,包含所有指定标签名的元素对象,找不到返回一个空类数组对象{length:0}

如果想要获取一个仅有的元素对象,需要加上[0],从类数组对象中0位置,取出唯一找到的一个元素对象

案例:name例子

注意:单选按钮时两个名字相同

n

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		<form action="">
			用户名:<input type="text" name="uname"></br>
			性别:<input type="radio" name="sex" value=1>男
			     <input type="radio" name="sex" value=0>女
		</form>
		<script>
		//查找name为sex的两个radio元素
		var radio=document.getElementsByName("sex");
		console.log(radio);
		
		//查找name为uname的一个文本框
		var txtName=document.getElementsByName("uname")[0];
		console.log(txtName);
		</script>
	</body>
</html>

通过选择器查找元素 2个函数

   一个元素

会查找所有后代

  只要一个元素藏的深,查找条件比较复杂时,都可以用选择器查找元素

  var 一个元素对象=任意父元素.querySelector("选择器");

  如果找到,返回一个元素的对象,如果没找到,返回null

案列:找出<p>学习</p>

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		<span>Hello World</span>
		<span>可爱</span>
		<ul id="nav"> 
			<li class="item">电影</li>
			<li class="item">综艺
				<ul>
					<li class="item active">跑男</li>
					<li class="item">爸爸</li>
					<li class="item">极限</li>
					<p>学习</p>
				</ul>
			</li>
			<li class="item">剧集</li>
		</ul>
		<script>
		var study=nav.querySelector("p");
		console.log(study);
		</script>
	</body>
</html>

  多个元素

 var 类数组对象=任意父元素.querySelectorAll("选择器")

 找到,返回类数组对象,包含找到所有找到符合要求的Dom元素对象,没找到,返回{length:0}

案列:查找nav下的所有li

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		<span>Hello World</span>
		<span>可爱</span>
		<ul id="nav"> 
			<li class="item">电影</li>
			<li class="item">综艺
				<ul>
					<li class="item active">跑男</li>
					<li class="item">爸爸</li>
					<li class="item">极限</li>
				</ul>
			</li>
			<li class="item">剧集</li>
		</ul>
		<script>
		var lis=nav.querySelectorAll("li");
		console.log(lis);
		</script>
	</body>
</html>

获取修改元素内容 

获取内容

获取开始标签到结束标签之间的原始HTML内容(<开始标签>  .........<结束标签>)

元素.innerHTML

修改内容:先将内容交个浏览器解析,解析后,返回门外汉也能看懂的内容

元素.innerHTML=“”

获取开始标签到结束标签之间的纯文本内容

元素.textContent

将特殊符号翻译为正文,并去掉内嵌的标签

修改内容:直接显示内容,不交给浏览器解析

元素.textContent=“”

案例:innerHTML与textContent获取内容

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		<h3>来自&lt;&lt;<a href="#">新华社</a>&gt;&gt;的消息</h3>
		<script>
		 //获取h3的内容,先找到位置再获取
		 var h3=document.getElementsByTagName("h3")[0];
		 console.log(h3.innerHTML);
		//获取h3的存文本内容
		 console.log(h3.textContent);
		</script>
	</body>
</html>

 案例:innerHTML与textContent修改内容

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		<h2></h2>
		<h3></h3>
		<script>
		//innerHTml修改内容
		var h2=document.getElementsByTagName("h2")[0];
		h2.innerHTML=`来自&lt;&lt;<a href="#">新华社</a>&gt;&gt;的消息`;
		 
		//textContent修改内容
		var h3=document.getElementsByTagName("h3")[0];
		h3.textContent=`来自&lt;&lt;<a href="#">新华社</a>&gt;&gt;的消息`;
		</script>
	</body>
</html>

表单元素值获取修改

元素.value

表单元素没有结束标签,所以innerHTML ,textContent无法使用,可以用value属性

案例:获取文本框里的内容

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		<input id="keyword"/><button id="btn">百度一下</button>
		<script>
	     var btn=document.getElementById("btn");
		 btn.onclick=function(){
			 //获取id为keyword的文本框值
			 var keyword=document.getElementById("keyword");
			 var value=keyword.value;
			 //trim去掉开头结尾的空字符
			 if(value.trim()!=""){
				 console.log(`搜索${value}的内容`);
			 }
		 }
		</script>
	</body>
</html>

属性

字符串类型的HTML标准属性

html标准中规定的,值为字符串的html属性

eg:id class name value title href arc

旧核心的DOM4个函数

      获取一个元素的属性值:元素.getAttribute("属性名")

      修改一个元素的属性值:元素.setAttribute("属性名”,“新属性值”)

      判断一个元素上是否包含某个属性 元素.hasAttribute("属性名")

      移除一个元素上的属性:元素.removeAttribute("属性名")

案列:就核心的dom4个函数

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
	<a id="bone" href="#" title="骨头">人体有多少骨头</a>
	<script>
	  var bone=document.getElementById("bone");
	  //获取a标签title的属性值
	  console.log(bone.getAttribute("title"));
	  
	  //修改a标签title的属性值
	  bone.setAttribute("title","身体组成成分");
	  console.log(bone.getAttribute("title"));
	  
	  //判断标签a上有没有href属性
	  console.log(bone.hasAttributes("href"));//true
	  
	  //移除标签a上的title属性
	  bone.removeAttribute("title");
	  console.log(bone.getAttribute("title"));//null
	  //不知道为什么这个打印出来是true,元素显示上已经没它了
	  //console.log(bone.hasAttributes("title"));
	</script>
	</body>
</html>

新HTML DOM

获取一个元素的属性值:元素.属性名

修改一个元素的属性值:元素.属性名

判断一个元素上是否包含某个属性: 元素.属性名!==" "

移除一个元素上的属性:元素.属性名=" "

注意:class属性,class已经被ES6定义为关键字,所以用className代替

案例:HTML DOM

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
	<a id="bone" href="#" title="吃饭">好好生活</a>
	<script>
	  var bone=document.getElementById("bone");
	  //获取a标签title的属性值
	  console.log(bone.title);//吃饭
	  
	  //修改a标签title的属性值
	  bone.title="煮饭";
	  console.log(bone.title);//煮饭
	  
	  //判断标签a上有没有href属性
	  console.log(bone.href!=="");//true
	  
	  //移除标签a上的title属性
	  bone.title="";
	</script>
	</body>
</html>

bool类型的HTML标准属性-----------不懂

凡是不用写属性值,只要放在元素开始标签中,就能起作用。比如disabled,checked,selected...

但是旧核心的DOM只支持字符串类型属性,不支持bool类型属性。

bool类型的HTML标准属性,用HTML DOM 

访问方式 元素.属性名,并且属性值不许是bool值,true或false

css的状态伪类

:cheacked 专门匹配选中的单选按钮和复选框

:disabled 专门匹配禁用的元素

自定义的扩展属性   

程序员根据自身需要,自发添加的定义属性。代替id选择器、类选择器、标签选择器等,作为查找触发事件的元素条件。

查找触发事件元素,一律使用自定义属性作为查找条件

<元素 data-自定义属性名=“属性值”>

 元素.dataset.自定义属性名

dataset可自动收集元素开始标签中,一切以data开头的自定义属性,集中保存起来备用。

使用dataset访问自定义属性时,不用加data-前缀,直接写属性名。   

案列:自定义属性案列


 

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		<button data-n="0">按钮</button>
		<script>
		//查找带有data-n属性的元素
		var btn=document.querySelector("[data-n]");
		btn.onclick=function(){
		//获得当前按钮身上data-n属性的值,转为整数
		var n=parseInt(
		//this.getAttribute("data-n"); DOM方法
		this.dataset.n
		);
		n++;
		//将新的n,放回当前按钮的data-n属性中报存
		//this.getAttribute("data-n",n);
		this.dataset.n=n;
		}
		</script>
	</body>
</html>

修改样式

修改内联样式   

这种是script里修改

元素.style.css属性名=“属性值;”    等价于  <元素 style="css属性:属性值;">

  注意:如果css属性名中包含-,则必须更名为去横线变驼峰。但是,虽然在js中改了名字,可是实际操作的还是原来的css属性

eg: z-index  ===  元素.zIndex                            font-size  ===  元素.fontSize

     background-color ===  元素.backgroundColor  

    和长度、大小、距离有段的数值,必须加单位

案例:字体颜色改变

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<style>
		span{
			color:red;
		}
		</style>
	</head>
	<body>
	<span>我爱学习</span>
	<script>
	var span=document.getElementsByTagName("span")[0];
	//把红色变为绿色
	span.style.color="green";
	</script>
	</body>
</html>

 获取样式getComputedStyle  

.style属性,无法获取样式表中的样式,如果使用.style获取css属性值,会丢掉一大部分css属性值

获得元素的完整的css属性,要用计算后的样式,就是最终应用到元素上的所有样式的总和

      1.获取一个元素计算后的所有属性的整体

        var style=getComputedStyle(元素对象)

      2.从style结果对象中,单独访问我们需要的某一个css属性

         style.css属性名

 注意: 计算后的样式,都是只读的,禁止修改。

            想要修改一个元素的样式,用元素.style.css属性,因为内联样式优先级最高

案例:getComputedStyle

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<style>
		h2{
			background-color:pink;
		}
		</style>
	</head>
	<body>
	 <h2 id="roll" style="color:green">努力学习</h2>
	<script>
	 var rose=document.getElementById("roll");
	 
	 //获取rose计算后的所有样式的集合
	 var raw=getComputedStyle(rose);
	 
	 //获取努力学习的字体颜色
	 console.log(raw.color);
	 
	 //获取努力学习的背景颜色
	 console.log(raw.backgroundColor);
	 
	 //获取努力学习的字号
	 console.log(raw.fontSize);
	 
	 //修改努力学习 字体大小
	 rose.style.fontSize="64px"
	 console.log(raw.fontSize);
	 
	</script>
	</body>
</html>

批量修改一个元素的css属性

只要批量修改一个元素的多个css属性,都用class代替.style方式

步骤2步

1先在css中提前准备好几套class预案

2在js中,根据不同的情况,选择1对应的class,设置到对应的元素上

  案列:带表单的验证

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<style>
		table{
			width:700px;
		}
		td:first-child{
			width:60px;
		}
		td:nth-child(2){
			width:200px;
		}
		td:first-child+td{
			width:200px;
		}
		td span{
			color:red;
		}
		.vali_info{
			display: none;
		}
		.txt_focus{
			border-top: 2px solid black;
			border-left: 2px solid black;
		}
		.vali_success,.vali_fail{
			background-repeat: no-repeat;
			background-position: left center;
			display: block;
		}
		.vali_success{
			background-image:url("img/add.png");
			padding-left: 20px;
			width: 0px;
			height:20px;
			overflow: hidden;
		}
		.vali_fail{
			background-image: url("img/subtract.png");
			border:1px solid red;
			background-color: #ddd;
			color:red;
			padding-left: 30px;
		}
		</style>
	</head>
	<body>
		<form id="form1">
			<h2>增加管理员</h2>
			<table>
				<tr>
					<td>姓名:</td>
					<td>
						<input name="username"/>
					     <span>*</span>
					</td>
					<td>
						<div class="vali_info">
							10个字符以内的字母、数字或下划线的组合
						</div>
					</td>
				</tr>
				<tr>
					<td>密码:</td>
					<td>
						<input type="password" name="pwd"/>
						 <span>*</span>
					</td>
					<td>
						<div class="vali_info">6位数字</div>
					</td>
				</tr>
				<tr>
					<td></td>
					<td colspan="2">
						<input type="submit" value="保存"/>
						<input type="reset" value="重填"/>
					</td>
				</tr>
			</table>
		</form>
		<script>
		//当姓名文本框失去焦点时触发,先找到它
		var txtName=document.getElementsByName("username")[0];
		// 绑定事件处理函数
		txtName.onblur=function(){
			// this 当前姓名文本框
			// 查找要修改的元素
			var div=this.parentElement.nextElementSibling.children[0];
			// 当前td    下一个td   下一个td下的div
			// 定义正则表达式,描述姓名文本框的规则
			var reg=/^\w{1,10}$/;
			var result=reg.test(this.value);
			// 如果验证通过
			if(result==true){
				// 就设置div的class为vali_success
				div.className="vali_success";
			}else{
				// 就设置div的class为vali_fail
				div.className="vali_fail";
			}
		}
		</script>
	</body>
</html>

添加删除替换元素------在script里

dom树 --render tree 加载树(css挂载)---排版----绘制网页内容

     

 先创建一个新的空元素

var 新元素=document.createElement("标签名”)

给新元素添加属性

元素.属性名=“属性值”

将新元素对象,挂载到DOM数上指定的父元素下------3种

        在父元素下所有直接子元素末尾追加新元素:

        父元素.appendChild(新元素)

        将新元素插入到一个父元素下现有子元素之前

       父元素.insertBrfore(新元素,现有元素)

      用新元素替换一个父元素下现有子元素

      父元素.replaceChild(新元素,现有元素)

删除元素

父元素.removeChild(子元素)

补充:第二种添加元素和元素内容的方法

createElement ------添加空的元素节点/创建一个新的xx元素

createTextNode-------创建文本节点,通过文本节点添加文本内容

    案列:创建添加元素

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		<script>
		//创建一个a元素
		var a=document.createElement("a");
		a.href="http://baidu.com";
		a.innerHTML="欢迎访问百度";
		//在控制台上打印出内容
		console.log(a);
		
		//将a追加到body结尾,这样就会在网页上显示
		document.body.appendChild(a)
        
        //删除元素
	   //document.body.removeChild(a)
	   
		</script>
	</body>
</html>

案列2:创建添加一个新的元素内容

 

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<style>
			div[id="div1"]{
				width: 300px;
				height: 300px;
				background-color: skyblue;
			}
			div{
				width: 300px;
				height: 100px;
				background-color: deeppink;//粉色
			}
		</style>
	</head>
	<body>
		<div id="div1">
			<p id="p1">这是一个段落</p>
		</div>
		<script>
			// 创建了一个新的div
			var newp=document.createElement("div");
			// 在新的div上面追加文本内容
			var node=document.createTextNode("我刚刚出生啦");
			newp.appendChild(node);
			var element=document.getElementById("div1");
			element.appendChild(newp);
		</script>
	</body>
</html>

文档片段对象

如果父元素已经在DOM树上,需要添加多个平级子元素,应该借助于文档片段对象。

 内存中临时保存多个平级子元素的虚拟父元素

  创建文档片段对象

  var 文档片段对象=document.createDocumentFragment();

 将多个平级子元素,追加到文档片段对象

 文档片段对象.appendChild(子元素)

将文档对象一次性添加到Dom树上指定父元素下

父元素.appendChild(文档片段对象)

注意:当文档片段对象将多个平级子元素添加到指定父元素下后就释放了,不会成为页面上一级元素

尽量减少操作DOM树的次数

每操作一次DOM树,浏览器都会重排重绘,极大的影响页面加载效率

如何做

 如果同时添加父元素和子元素,应该现在内存中将所有子元素添加到父元素上,最后再将父元素一次添加到DOM树上。这样就只需要一次重排重绘。

案列:动态创建表格  ---减少操作Dom树次数

之前的优化代码本人已经删除,这个代码一步到位

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<style>
			table{width:600px; border-collapse:collapse;
					text-align:center;
				}
				td,th{border:1px solid #ccc}
		</style>
	</head>
	<body>
		<div id="data">
		    <table>
		      <thead>
		        <tr>
		          <th>员工姓名</th>
		          <th>薪资</th>
		          <th>年龄</th>
		        </tr>
		      </thead>
			  <tbody>
			          <!--通过js添加,已经在DOM树上了!-->
			        </tbody>
 
		    </table>
		  </div>
		<script>
			var json=[
			    {
			      "ename":"Tom", 
			      "salary":11000, 
			      "age":25
			    },
			    {
			      "ename":"John", 
			      "salary":13000, 
			      "age":28
			    },
			    {
			      "ename":"Mary", 
			      "salary":12000, 
			      "age":25
			    },
				{
				  "ename":"Mary", 
				  "salary":12000, 
				  "age":25
				},
			  ];
			  
			  //创建文档片段对象
			  var frag=document.createDocumentFragment(); 
			  //遍历json数组中每个员工对象,每遍历一个员工对象,就创建一个tr,追加到frag中
			  for(var emp of json){
				  var tr=document.createElement("tr");
				  frag.appendChild(tr);
				  //遍历当前员工对象中每个属性
				  for(var key in emp){
					  //每遍历一个属性,就创建一个td
					  var td=document.createElement("td");
					  //设置td的内容为当前对象当前属性的属性值
					  td.innerHTML=emp[key];
					  //将td追加到tr
					  tr.appendChild(td);
				  }
			  }
			  //当所有tr和td都添加到frag中,最后再将frag追加到tbody中
			  var tbody=document.querySelector("#data>table>tbody");
			  tbody.appendChild(frag);
		</script>
	</body>
</html>

HTML DOM常用对象

html dom对个别比较常用,又比较复杂的元素提供了一套简化版的操作。

但它只对个别元素提供了简化版操作,不是所有元素都能简化。并且它的简化没有jq和vue简单。

<img元素>

  只有在新建img元素时,才有简化的做法

 旧DOM            var img=document.createElement("img");

 HTML DOM     var img=new image()

<form元素>

  网页已将所有form元素集中保存在了document.forms集合中。 

form元素对象已将内部所有表单元素集中保存在了form.elements集合中。

快速获取页面中某一个form元素

 var form元素=docuemnt.forms[i]

  

快速获得form内某个表单元素

标准:form.elements[i下标/id/name名]

           简写:如果表单元素有name名属性,简写为form.name

表单元素身上都有一个.focus()函数,可以让当前表单元素自动获得焦点!

 案列:from元素

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		<form>
			姓名:<input type="text"/><br/>
			密码:<input type="password"/><br/>
			<button>按钮</button>
		</form>
		<form>
			姓名1:<input type="text"/><br/>
			密码1:<input type="password" name="pwd"/><br/>
			<button>按钮</button>
		</form>
		<script>
		//获取页面中某一个form元素---这个获取到的是第二个form
		var form=document.forms[1];
		console.log(form);
        //获取到了第二个form的第二个值
		var s=form.elements[1];
		console.log(s);
		</script>
		
	</body>
</html>

案列:带样式的表单验证

<!DOCTYPE html>
<html>

<head>
  <meta charset="UTF-8">
  <title>实现带样式的表单验证</title>
  <style>
    table {
      width: 700px
    }

    td:first-child {
      width: 60px
    }

    td:nth-child(2) {
      width: 200px
    }

    td:first-child+td {
      width: 200px
    }

    td span {
      color: red
    }

    .vali_info {
      display: none;
    }

    .txt_focus {
      border-top: 2px solid black;
      border-left: 2px solid black;
    }

    .vali_success,
    .vali_fail {
      background-repeat: no-repeat;
      background-position: left center;
      display: block;
    }

    .vali_success {
      background-image: url("images/ok.png");
      padding-left: 20px;
      width: 0px;
      height: 20px;
      overflow: hidden;
    }

    .vali_fail {
      background-image: url("images/err.png");
      border: 1px solid red;
      background-color: #ddd;
      color: Red;
      padding-left: 30px;
    }
  </style>
</head>

<body>
  <form id="form1">
    <h2>增加管理员</h2>
    <table>
      <tr>
        <td>姓名:</td>
        <td>
          <input name="username" />
          <span>*</span>
        </td>
        <td>
          <div class="vali_info">
            10个字符以内的字母、数字或下划线的组合
          </div>
        </td>
      </tr>
      <tr>
        <td>密码:</td>
        <td>
          <input type="password" name="pwd" />
          <span>*</span>
        </td>
        <td>
          <div class="vali_info">6位数字</div>
        </td>
      </tr>
      <tr>
        <td></td>
        <td colspan="2">
          <input type="submit" value="保存" />
          <input type="reset" value="重填" />
        </td>
      </tr>
    </table>
  </form>
  <script>
    
    //本例中: 当姓名文本框失去焦点时触发验证
   // var txtName=document.getElementsByName("username")[0];
   //form优化
   //获得form元素
   var form=document.forms[0];
   var txtName=form.elements["username"]; //这部还可以这样写  var txtName=form.username
   //文本框自动获得焦点
    txtName.focus();
    //2. 绑定事件处理函数
    txtName.onblur=function(){
      //this->当前姓名文本框
      //3. 查找要修改的元素
      //本例中: 要修改文本框的爹的下一个兄弟的第一个孩子
      var div=this //当前文本框
              .parentElement //当前td
              .nextElementSibling //下一个td
              .children[0]; //下一个td下的div
      //4. 修改元素
      //定义正则表达式,描述姓名文本框的规则
      var reg=/^\w{1,10}$/;
      //用正则表达式去验证当前姓名文本框的内容
      var result=reg.test(this.value);
      //如果验证通过
      if(result==true){
        //就设置div的class为vali_success
        div.className="vali_success";
      }else{//否则如果验证不通过
        //就设置div的class为vali_fail
        div.className="vali_fail";
      }
    }
  </script>
</body>

</html>

table元素

 table结构是所有html元素中最复杂的。所有html dom提供了一套函数,逐级管理table中的元素

    table管着行分组

               添加行分组(两个功能)

                  var thead=table.createTHeada();    创建了thead元素并添加到table

                  var tbody=table.createTBody();

                  var tfoot=table.createTFoot();

           删除行分组

                table.deteleTHead()

               table.deleteTFoot()

          获取行分组

            table.tHead

           table.tFoot

         获取tbody   

        table.tBodies[i]

                   注意:一个table中只能有一个thead、tfoot.。但可以有多个tbody,保存在一个tBodies的集合中。必须用下标才能获取某一个tbody。所以table也就没法删除tbody.

    行分组管着行

 添加行   

     var tr=行分组.insertRow(i)     

          

 开头插入新行   行分组.   insertRow(0)

    末尾追加行    行分组.insertRow

注意:创建了新空行,再将新行添加到行分组。

           如果行分组已经有现有行了,则插入的行会把当前位置的行及之后的行向后挤一个位置,新行再占据当前下标位置

 删除行

       行分组.deteleRow(i)     i,要求必须是行分组内的相对下标位置

     rowindex 属性-----每个行对象自带属性rowindex,记录行在整个表中的下标位置 

      行在整个表中的下标位置=rowindex所表示的下标

       假设想删 i 行  ,  行分组.deleteRow(tr.rowIndex),删除的就是i+1行

       删除table中某一行,标准写法:table.deleteRow(tr.rowindex).

 获取行

       行分组.row[i]   代替  行分组.children[i]

    行管理格

        添加格  var td=行.insertCell()    //先创建一个新的td,在把td追加到tr中

         删除格:行.deleteCell(i). //删除行中下标为i的格。

         获取格: 行.cells[i]

   案例:删除表格中某一行数据

         

<!DOCTYPE HTML>
<html>
<head>
<title>动态创建表格</title>
<meta charset="utf-8" />
<style>
	table{width:600px; border-collapse:collapse;
		text-align:center;
	}
	td,th{border:1px solid #ccc}
</style>

</head>
<body>
	<div id="data">
    <table>
      <thead>
        <tr>
          <th>员工姓名</th>
          <th>薪资</th>
          <th>年龄</th>
		  <th>操作</th>
        </tr>
      </thead>
    </table>
  </div>
  <script>
	var json=[
    {
      "ename":"Tom", 
      "salary":11000, 
      "age":25
    },
    {
      "ename":"John", 
      "salary":13000, 
      "age":28
    },
    {
      "ename":"Mary", 
      "salary":12000, 
      "age":25
    }
  ];
	(function(){  
  //1. 创建tbody,追加到table中
  var tbody=document.createElement("tbody");
   //需要先查找一下
  var table=document.querySelector("#data>table");


  //2. 遍历json数组中每个员工对象
  for(var emp of json){
    //每遍历一个员工对象,就创建一个tr,追加到tbody中
   // var tr=document.createElement("tr");
    //tbody.appendChild(tr);
	
	// 简化写法
	var tr=tbody.insertRow();//末尾追加行
	//var tr=tbody.insertRow[0];//开头插入行  //这样出不来
	
    //进一步遍历当前员工对象中每个属性
    for(var key in emp){
      //每遍历一个属性,就创建一个td
     // var td=document.createElement("td");
	   //tr.appendChild(td);
	   var td=tr.insertCell();
      //设置td的内容为当前对象当前属性的属性值
      td.innerHTML=emp[key];
	  
	  
    }
	// 在添加一个td
	//var td=document.createElement("td");
	//tr.appendChild(td);
	var td=tr.insertCell();
	//在td中添加一个button
	var btn=document.createElement("button");
	td.appendChild(btn);
	//设置按钮的位置,并为按钮绑定单击事件
	btn.innerHTML="x";
	btn.onclick=function(){
		//this.innerHTML="❀"; 测试
		 //查找当前按钮父元素td的父元素 tr
		 var tr=this.parentElement.parentElement;
		 console.log(tr);
		 var ename=tr.cells[0].textContent;
		 //var ename=tr.children[0].innerHTML;
		 console.log(ename);
		 //先跟用户确认,是否继续删除
		 var result=confirm(`是否继续删除${ename}`);
		 //用户点击确认,表示用户同意删除
		 if(result==true){
			 //最终效果
			 table.deleteRow(tr.rowIndex);
		 }
	}
  }

  //再将tbody一次性添加到DOM树
    table.appendChild(tbody);
  
   })()
  </script>
</body>
</html>

浏览器三大对话框

输入框

包含一个文本框,可输入内容。并且可用返回值接住用户输入的内容。

               var 内容=prompt("提示信息");

      

警告框

只有一个确认按钮的提示框,没有选择

              alert("提示信息");

确认框

有一个确认按钮和一个取消按钮的对话框。用户可用选择确认或取消。程序中,还可以通过返回值接住用户点击的结果。

  var 结果=confirm("提示信息");  

  结果一个为true,一个为false

 但这三个所用不多,因为它用兼容性问题,不同浏览器显示的对话框会有差别。它的样式你不能修改

案列

购物车案例

运行效果:

jsDOM购物车效果展示

更清晰视频地址jsDOM购物车效果展示_哔哩哔哩_bilibili

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<style>
		table{
			width:600px;
			text-align: center;
			border-collapse: collapse;
		}
		th,td{
			border: 1px solid black;
		}
		[colspan="3"]{
			text-align: right;
		}
		</style>
	</head>
	<body>
		<table id="data">
			<thead>
			 <tr>
			 	<th>商品名称</th>
			 	<th>单价</th>
			 	<th>数量</th>
				<th>小计</th>
			 </tr>
			</thead>
			<tbody>
				<tr>
					<td>iphone6</td>
					<td>¥4488.00</td>
					<td>
						<button>-</button>
						<span>1</span>
						<button>+</button>
					</td>
					<td>¥4488.00</td>
				</tr>
				<tr>
					<td>iphone6 plus</td>
					<td>¥5288.00</td>
					<td>
						<button>-</button>
						<span>1</span>
						<button>+</button>
					</td>
					<td>¥5288.00</td>
				</tr>
				<tr>
					<td>ipad Air2</td>
					<td>¥4288.00</td>
					<td>
						<button>-</button>
						<span>1</span>
						<button>+</button>
					</td>
					<td>¥4288.00</td>
				</tr>
			</tbody>
			<tfoot>
				<tr>
					<td colspan="3">Total:</td>
					<td>¥14064.00</td>
				</tr>
			</tfoot>
		</table>
		<script>
		//通过按钮实现数量增加减少功能
		//找到按钮
		var table=document.getElementById("data");
		var btns=table.getElementsByTagName("button");
		//单击按钮产生数量加减效果
		for(var btn of btns){
			btn.onclick=function(){
			//先找到数量
			var span=this.parentElement.children[1];
			var n=parseInt(span.innerHTML);
			if(this.innerHTML=="+"){
				n++;
			}else if(n>1){
				n--;
			}
			span.innerHTML=n;
			
			//计算小计
			//找到价格并切分人民币符合
			var td=this.parentElement.nextElementSibling;
			var price=parseFloat(this.parentElement.previousElementSibling.innerHTML.slice(1));
			//小计
			var sum=price*n;
			td.innerHTML=`¥${sum.toFixed(2)}`;
			
			//总计
			//找到它并修改
			var lastTd=table.querySelector("tfoot>tr>td:last-child");
			var tds=table.querySelectorAll("tbody>tr>td:last-child");
			var total=0;
			//累加小计
			for(var td of tds){
				total+=parseFloat(td.innerHTML.slice(1));
			}
			lastTd.innerHTML=`¥${total.toFixed(2)}`;
			
			var lastTd=table.querySelector("tfoot>tr>td:last-child");
			var tds=table.querySelectorAll("tbody>tr>td:last-child");
			var total=0;
			//累加小计
			for(var td of tds){
				total+=parseFloat(td.innerHTML.slice(1));
			}
			lastTd.innerHTML=`¥${total.toFixed(2)}`;
			
			}
		}
		</script>
	</body>
</html>

手风琴效果

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<style>
		div{
			float: left;
			height:100px;
			line-height: 100px;
		}
		#d1,#d3{
			background-color: #ccff00;
		}
		#d2{
			cursor: pointer;
			background-color: #00BFFF;
		}
		</style>
	</head>
	<body>
		<div id="d1">树形列表</div>
		<div id="d2">&lt;&lt;</div>
		<div id="d3">内容的主体</div>
		<script>
		var d2=document.getElementById("d2");
		//点d2显示或隐藏d1
		d2.onclick=function(){
			var d1=document.getElementById("d1");
			//当d2箭头为<<就隐藏
			//当d2为>>就打开
			if(this.innerHTML=="&lt;&lt;"){
				//等价于<div id="d1" style="display:none">
				d1.style.display="none";
				this.innerHTML="&gt;&gt;"
			}else{
				//写block的话,行内情况不对,所以不写默认就是显示
				d1.style.display="",
				this.innerHTML="&lt;&lt;"
			}
		}
		</script>
	</body>
</html>

点击隐藏展示效果

图片没有找到合适的

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<style>
		li{
			list-style: none;
		}
		li span{
			padding-left:40px;
			cursor: pointer;                                                              ,
			/* background:url("img/add.png") no-reapat center left; */
		}
		li ul{
			display: none;
		}
		/* .open{
			background:url("img/subtract.png") no-repeat center left;
		} */
		.open+ul{
			display: block;
		}
		img{
			width:70px;
			heigh:70px;
		}
		</style>
	</head>
	<body>
		<ul class="tree">
			<li>
				<span class="open">考勤管理</span>
				<ul>
					<li>日常考勤</li>
					<li>请假申请</li>
					<li>加班/出差</li>
				</ul>
			</li>
			<li>
				<span>协同办公</span>
				<ul>
					<li>公文流转</li>
					<li>文件中心</li>
					<li>内部邮件</li>
					<li>即时通信</li>
					<li>短信提醒</li>
				</ul>
			</li>
		</ul>
	</body>
	<script>
	var spans=document.querySelectorAll("li>span");
	for(var span of spans){
		span.onclick=function(){
			//this指当前点击的span
			var spans=document.querySelectorAll("li>span");
			//先遍历,清除所有span上的class,class用className代替
			if(this.className=="open"){
				this.className=""
			}else{
				for(var span of spans){
					span.className=""
				}
				this.className="open"
			}
		}
	}
	</script>
</html>

全选案列

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		<h2>管理员列表</h2>
		<table border="1px" width="500px">
			<thead>
				<tr>
					<th><input type="checkbox"/>全选</th>
					<th>管理员ID</th>
					<th>姓名</th>
					<th>操作</th>
				</tr>
			</thead>
			<tbody>
				<tr>
					<td><input type="checkbox"/></td>
					<td>1</td>
					<td>Tester</td>
					<td>修改 删除</td>
				</tr>
				<tr>
					<td><input type="checkbox"/></td>
					<td>2</td>
					<td>Manager</td>
					<td>修改 删除</td>
				</tr>
				<tr>
					<td><input type="checkbox"/></td>
					<td>3</td>
					<td>Analyst</td>
					<td>修改 删除</td>
				</tr>
				<tr>
					<td><input type="checkbox"/></td>
					<td>4</td>
					<td>Admin</td>
					<td>修改 删除</td>
				</tr>
			</tbody>
		</table>
		<button>删除选定</button>
		<script>
		//功能一 点击全选按钮,下面4个全选中
		//通过选择器查找全选按钮
		var chbAll=document.querySelector("thead input");
		//单击按钮时绑定下面4个按钮
		chbAll.onclick=function(){
			//通过选择器查找4个按钮
			var chbs=document.querySelectorAll("tbody input");
			for(var chb of chbs){
				chb.checked=this.checked;
				//this指代全选按钮,checked表示选中
			}
		}
		//功能二:4个按钮没全选中就取消全选按钮
		var chbs=document.querySelectorAll("tbody input");
		for(var chb of chbs){
			chb.onclick=function(){
				//查找全选按钮
				var chbAll=document.querySelector("thead input");
				//只要一个没选择就不能全选,:checked表示选中复选框单选框
				var unchecked=document.querySelector("tbody input:not(:checked)");
				//判断全选和未选中关系
				if(unchecked!=null){
					chbAll.checked=false;
				}else{
					chbAll.checked=true;
				}
			}
		}
		</script>
	</body>
</html>

选项卡

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title></title>
        <style>
            * {
              margin: 0;
              padding: 0;
            }
        
            #tab li {
              float: left;
              list-style: none;
            }
        
            #tab li a {
              display: inline-block;
              text-decoration: none;
              width: 80px;
              height: 40px;
              line-height: 40px;
              text-align: center;
              color: #000;
            }
        
            #container {
              position: relative;
            }
        
            #content1,
            #content2,
            #content3 {
              width: 300px;
              height: 100px;
              padding: 30px;
              position: absolute;
              top: 40px;
              left: 0;
            }
        
            #tab li:first-child,
            #content1 {
              background-color: lightblue;
            }
        
            #tab li:first-child+li,
            #content2 {
              background-color: palegreen;
            }
        
            #tab li:first-child+li+li,
            #content3 {
              background-color: yellowgreen;
            }
          </style>

    </head>
    <body>
        <h2>实现多标签页效果</h2>
          <div class="tabs">
            <ul id="tab">
              <li><a href="#content1" data-toggle="tab" data-id="content1">10元套餐</a></li>
              <li><a href="#content2" data-toggle="tab" data-id="content2">30元套餐</a></li>
              <li><a href="#content3" data-toggle="tab" data-id="content3">50元包月</a></li>
            </ul>
            <div id="container">
                <!-- 加style 然初始页面是第一个 -->
               <div id="content1" style="z-index:10"> 
                10元套餐详情:<br />&nbsp;每月套餐内拨打100分钟,超出部分2毛/分钟
              </div>
              <div id="content2">
                30元套餐详情:<br />&nbsp;每月套餐内拨打300分钟,超出部分1.5毛/分钟
              </div>
              <div id="content3">
                50元包月详情:<br />&nbsp;每月无限量随心打
              </div>
            </div>
          </div>
          <script>
		  // 注意:复制代码后如果点不动,重新写一下onclick就可以了
              //查找触发事件的元素
              //首先绑定两个之间有联系
              //查找所有带有data-toggle属性,且属性值为tab的所有a元素
              var tabs=document.querySelectorAll("[data-toggle=tab]");
             //定义一个z,保存z-index的值
             var z=10;
              //所有tab都可点击,所有遍历
              for(var tab of tabs){
                  tab.onclick=function(){
                      //this指当前点击的a元素
                      //查找要修改的a与元素
                      //先从当前a自己身上查找对应div的id
                      var id=this.dataset.id;
                      //用id查找对应的div元素
                      var div=document.getElementById(id);
					  this.dataset.id=this.getAttribute("data-id")
                      z++;//将z变量的值加1
                      //修改div的z-index属性值为最大值
                      div.style.zIndex=z;//js中不能随便写-,所以所以css中带有-的属性名一律去掉横线变驼峰。     
                  }
              }
              
          </script>
    </body>
</html>

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值