JavaScript学习笔记(四)
DOM
一、DOM概述
DOM(Document Object Model):文档对象模型,是W3C组织结构推荐的处理可以扩展标识语言的标准编程接口(接口就需要有实现类:HTML和XML)。在网页上,组织页面(或者文档)的对象(标签)被组织在一个树形的结构中,用来表示文档中对象的标准模型,被称为DOM。
- 文档:把一个HTML文件看成一个文档,由于“万物皆对象”,所以我们可以把这个文档看成一个对象(document)
- XML:文件可以可以看成一个文档,侧重于数据存储
- HTML:展示信息,展示数据使用
- 页面中的每一个标签,都是一个元素(element),每一个元素都是可以看成一个对象(元素==标签)
- 对标签:
<元素名称 属性=“属性值”>元素内容(文本)</元素名称>
- 单标签:
<元素名称属性=“属性值”/>
- 文本也是可以看车一个对象(很少这么使用)
- 标签是可以进行嵌套,标签中包含标签,元素中有元素
- 对标签:
- 页面中的根元素(根标签):
<html>
,元素内容(有很多的标签组成) - 元素(element):页面中的所有的标签都是元素,元素就可以看成对象
- 节点(node):页面中所有的内容都是节点
- 标签节点
- 属性节点
- 文本节点
- 根节点root
二、元素对象
元素就是标签,获取HTML页面中标签对象的方式:
2.1 获取方式
<h3 name="tt">休闲</h3>
<p id="p1" style="background: deeppink;">分类:<strong>娱乐</strong></p>
<ul>
<li>小说</li>
<li name="tt">电视剧</li>
<li>电影</li>
</ul>
<p id="p2" class="userName">历史</p>
<strong class="userName book">武侠</strong>
<p class="userName">玄幻</p>
<p name="tt">都市</p>
(1).通过ID获取一个元素对象,如果没有返回null
console.log(document.getElementById("p1"));
console.log(document.getElementById("p2"));
(2).通过标签名
获取一组元素对象,,如果没有返回null
var bodyElement = document.getElementsByTagName("body");
console.log(bodyElement);
console.log(document.getElementsByTagName("p"));
console.log("body对象的元素内容中,可以继续获取对应的元素对象");
console.log(bodyElement[0],bodyElement.item(0));//数组转换为对象
console.log(bodyElement[0].getElementsByTagName("p"));
console.log(bodyElement.item(0).getElementsByTagName("p"));
(3).通过NAME属性获取一组元素对象,,如果没有返回null
var nameList = document.getElementsByName("tt");
console.log(nameList);
for(let i=0;i<nameList.length;i++){
console.log(nameList.item(i),nameList[i]);
}
(4).通过class属性获取一组元素对象,,如果没有返回null
var classList01 = document.getElementsByClassName("userName");
for(var element of classList01){
console.log(element);
}
var classList02 = bodyElement[0].getElementsByClassName("userName");
for(var element of classList02){
console.log(element);
}
(5).可以通过CSS选择器获取一个元素对象,没有返回null
注意:
querySelector()方法只能返回一个
返回多个用querySelectorAll()方法
console.log("===ID选择器")
console.log(document.querySelector("#p1"));
console.log(document.querySelector(".userName"));
console.log(document.querySelector("#p2","#p1"));//不推荐写法,只能返回具体的某一个
console.log("===类选择器")
var classList03 = document.querySelectorAll(".userName");
for(var element of classList03){
console.log(element);
}
console.log("===标签选择器")
var classList05 = document.querySelectorAll("p");
for(var element of classList05){
console.log(element);
}
console.log("===交集选择器")
var classList04 = document.querySelectorAll("p.userName");
for(var element of classList04){
console.log(element);
}
console.log("===后端选择器")
var classList06 = document.querySelectorAll("p strong");
for(var element of classList06){
console.log(element);
}
console.log("===多类选择器")
var classList07 = document.querySelectorAll(".userName.book");
for(var element of classList07){
console.log(element);
}
2.2 元素绑定事件方式
关于事件的处理,后续会详细说明,这里我们是演示元素对象绑定事件的两种方式(实际上有三种):
<h3>内联方式:直接书写JavaScript代码</h3>
<a href="javascript:;" onclick="window.location.href='http://www.baidu.com'">跳转到百度页面</a>
<h3>内联方式:执行某个函数</h3>
<button type="button" onclick="test01()">执行有名函数2222=window调用test02函数</button><br/>
<script>
function test01(){
console.log(this,Math.random(),"111111");
}
function test01(){
console.log(this,Math.random(),"22222");
}
test01();//直接调用,this==window
</script>
<h3>分离代码:执行某个有名函数</h3>
<button type="button" id="mybtn1">执行有名函数3333==this==当前对象</button><br/>
<script>
document.getElementById("mybtn1").onclick=test02;
function test02(){
console.log(this,Math.random(),this.type,"333333");
}
test02();//this==window
</script>
<h3>分离代码:执行某个匿名函数</h3>
<button type="button" id="mybtn2">执行有名函数4444</button><br/>
<script>
document.getElementById("mybtn2").onclick=function(){
console.log(this,Math.random(),this.type,"44444");
}
</script>
多个元素,循环绑定中的变量问题
直接遍历buttonList 索引是会发现点击每个按钮都是3,原因是使用了var定义.
<button type="button">按钮1</button>
<button type="button">按钮2</button>
<button type="button">按钮3</button>
<hr/>
<p>天枢</p>
<p>摇光</p>
<p>开阳</p>
<script>
window.onload=function(){
var buttonList = document.getElementsByTagName("button");
/**var没有块级作用域*/
for(var i=0;i<buttonList.length;i++){
var oBtn = buttonList[i];
console.log("传统的解决方案:给每个元素对象增加自定义的属性");
oBtn.number = i;
oBtn.onclick=function(){
console.log(this,Math.random(),this.number);/**i的输出情况*/
}
}
console.log("==========================");
var pList = document.getElementsByTagName("p");
console.log("使用let关键字,存在块级别作用域");
for(let i=0;i<pList.length;i++){
let objP = pList[i];
objP.onclick=function(){
console.log(this,Math.random(),i);
}
}
}
</script>
2.3 DOM中小案例
(1) 改变图片显示大小
<button type="button" id="myBtn">改变图片</button>
<img src="" alt="2" title="1" id="myImage">
<script>
window.onload=function (){
var myBtn = document.getElementById("myBtn");
var myImage = document.getElementById("myImage");
myBtn.onclick = function (){
myImage.src="../images/0002.jpg";
myImage.width = Math.trunc(Math.random()*100+300);
myImage.height = Math.trunc(Math.random()*100+300);
}
}
</script>
(2) 改变元素内容
<button type="button" id="btn1">获取元素内容-1</button>
<p id="p1">若有人兮<strong>山之阿</strong></p>
<button type="button" id="btn2">获取元素内容-2</button>
<p id="p2">表独立兮<strong>山之上</strong></p>
<button type="button" id="btn3">设置元素内容-3-转义</button>
<p id="p3"></p>
<button type="button" id="btn4">设置元素内容-4-识别</button>
<p id="p4"></p>
<script>
window.onload=function (){
let btn1 = document.getElementById("btn1");
let btn2 = document.getElementById("btn2");
let btn3 = document.getElementById("btn3");
let btn4 = document.getElementById("btn4");
console.log("1.获取元素内容方式");
btn1.onclick = function (){
let p1 = document.getElementById("p1");
console.log("存在浏览器兼容问题,获取元素内容:只能获取文本内容:"+p1.innerText);
}
btn2.onclick = function (){
let p2 = document.getElementById("p2");
console.log("获取元素内容(可以获取到<strong>标签):获取元素内容:"+p2.innerHTML);
}
btn3.onclick = function (){
let p3 = document.getElementById("p3");
p3.innerText = "采三秀<strong>于山间</strong>";
}
btn4.onclick = function (){
let p4 = document.getElementById("p4");
p4.innerHTML = "山中人兮<strong>芳杜若</strong>";
}
}
</script>
(3) 改变文本框数据
<input type="button" id="btn1" value="获取数据">
<input type="button" id="btn2" value="设置数据-1">
<input type="button" id="btn3" value="设置数据-2">
<hr/>
<input type="text" value="第一序列">
<input type="text" value="黎明医生">
<input type="text" value="救世主">
<script>
window.onload=function (){
let btn1 = document.getElementById("btn1");
let btn2 = document.getElementById("btn2");
let btn3 = document.getElementById("btn3");
let btn4 = document.getElementById("btn4");
btn1.onclick = function (){
console.log("排除类型为btn的元素");
let inputList = document.getElementsByTagName("body").item(0).getElementsByTagName("input");
for (let input of inputList){
if (input.type!= "button"){
console.log("获取文本框中的数据:"+input.getAttribute("value")+"\t"+input.value+"\t"+input["value"]);
}
}
}
let bookName1 = ["北颂","覆汉","仙秦","道宋"];
btn2.onclick = function (){
let inputList = document.getElementsByTagName("body").item(0).getElementsByTagName("input");
for (let input of inputList){
if (input.type!= "button"){
input.value = bookName1[Math.floor(Math.random()*4)];
}
}
}
let bookName2 = ["盛唐","强汉","大明","星火"];
btn3.onclick = function (){
let inputList = document.querySelectorAll("input[type='text']");//属性选择器
for (let input of inputList){
if (input.type!= "button"){
input.value = bookName2[Math.floor(Math.random()*4)];
}
}
}
}
</script>
(4) 恢复初始化,排它操作:固定模式(主要的是解题思路)
<input type="button" value="废土">
<input type="button" value="废土">
<input type="button" value="废土">
<input type="button" value="废土">
<input type="button" value="废土">
<input type="button" value="废土">
<input type="button" value="废土">
<script>
window.onload=function () {
let inputList = document.getElementsByTagName("input");
for (let i = 0; i < inputList.length; i++) {
let inputElement = inputList[i];
inputElement.onclick = function (){
//1.将文本恢复初始化
for (let o of inputList){
o.value="废土";
}
//2.修改当前对象属性
this.value = "第一序列";
}
}
}
</script>
(5) 单选框和复选框操作
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h3>单选框</h3>
<input type="radio" name="sex" value="boy">男生
<input type="radio" name="sex" value="girl">女生
<br/>
<button type="button" id="btn1">设置</button>
<button type="button" id="btn2">获取</button>
<hr/>
<h3>复选框</h3>
<input type="checkbox" name="hobby" value="football">足球
<input type="checkbox" name="hobby" value="basketball">篮球
<input type="checkbox" name="hobby" value="music">音乐
<br/>
<button type="button" id="btn3">设置</button>
<button type="button" id="btn4">获取</button>
<hr/>
<script>
window.onload=function() {
let radioArray = ["boy","girl"];
let radioList = document.getElementsByName("sex");
document.getElementById("btn1").onclick=function(){
let sex = radioArray[Math.trunc(Math.random()*2)];
//传统方式
for(let i=0;i<radioList.length;i++){
let r = radioList.item(i);
if(r.value==sex){
r.checked = true;//设置选中
}
}
}
document.getElementById("btn2").onclick=function(){
let sex ;
//传统方式
for(let i=0;i<radioList.length;i++){
let r = radioList.item(i);
if(r.checked){
sex=r.value;//获取数据
}
}
console.log(sex);
}
console.log("============================");
let checkboxArray = ["football","music"];
let checkboxList = document.getElementsByName("hobby");
document.getElementById("btn3").onclick=function(){
checkboxList.forEach(e=>{
console.log(e);
e.checked = checkboxArray.includes(e.value);
});
}
document.getElementById("btn4").onclick=function(){
var valueArray = [];
checkboxList.forEach(e=>{
if(e.checked){
valueArray.push(e.value);
}
});
console.log(valueArray.join())
}
}
</script>
</body>
</html>
(6) 下拉框选中和获取
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h3>下拉框</h3>
<select id="city">
<option value="">请选择城市</option>
<option value="1001">北京</option>
<option value="1002">上海</option>
<option value="1003">深证</option>
</select>
<br/>
<button type="button" id="btn1">设置</button>
<button type="button" id="btn2">获取</button>
<hr/>
<script>
window.onload=function() {
console.error("不用去遍历option对象(也可以通过遍历option对象,判断selected属性)")
let selectArray = [1001,1002,,1003];
let selectObj = document.getElementById("city");
document.getElementById("btn1").onclick=function(){
let city = selectArray[Math.trunc(Math.random()*3)];
selectObj.value = city;//设置选中
}
document.getElementById("btn2").onclick=function(){
console.log(selectObj.value);//获取
}
}
</script>
</body>
</html>
2.4 CSS样式
(1) 如何获取CSS样式
divObj.style方式只可用来获取行内样式
<head>
<meta charset="UTF-8">
<title>CSS</title>
<style>
#div1{
width: 200px;
background-color: pink;
border: 5px solid #aaa;
}
</style>
</head>
<body>
<div id="div1" style="height: 250px"></div>
</hr>
<button type="button" id="btn1">获取</button>
</hr>
<script>
window.onload = function (){
let divObj = document.getElementById("div1");
document.getElementById("btn1").onclick=function (){
console.error("divObj.style.属性方式只可用来获取行内样式");
console.log(divObj.style.width);
console.log(divObj.style.height);
console.error("divObj.currentStyle.属性方式只在IE浏览器有效,谷歌会报错");
//console.log(divObj.currentStyle.width);
console.error("非IE浏览器");
console.log(window.getComputedStyle(divObj,null).width);
console.log("调用方法");
alert("width:"+getStyle(divObj,"width"));
console.log("height:"+getStyle(+divObj,"height"));
console.log("复合样式:"+getStyle(divObj,"border")+"IE浏览器不能识别");
console.log("复合样式border颜色:"+getStyle(divObj,"borderColor"));
console.log("复合属性:"+getStyle(divObj,"background-color"));
}
//封装
function getStyle(obj,attr){
return obj.currentStyle?obj.currentStyle[attr]:window.getComputedStyle(divObj,null)[attr];
}
}
</script>
(2) 行内样式的设置
<div id="div1" style="height: 250px">第一序列</div>
</hr>
<button type="button" id="btn1">获取</button>
<button type="button" id="btn2">设置字体大小</button>
</hr>
<script>
window.onload = function (){
let divObj = document.getElementById("div1");
document.getElementById("btn1").onclick=function (){
console.log("复合属性:"+css(divObj,"font-size"));
}
document.getElementById("btn2").onclick=function (){
//属性用驼峰式命名法书写
//divObj.style.fontSize=Math.round(Math.random()*20)+21+"px";
//divObj.style.color="blue";
console.log("设置字体大小:");
css(divObj,"fontSize",Math.round(Math.random()*20)+21+"px");
}
//封装
function css(obj,attr,value){
if (arguments.length == 2){//形参长度为2则为获取样式
return obj.currentStyle?obj.currentStyle[attr]:window.getComputedStyle(divObj,null)[attr];
}else {//设置样式
obj.style[attr] = value;
}
}
}
</script>
classList 属性返回元素的类名,作为 DOMTokenList 对象。该属性用于在元素中添加,移除及切换 CSS 类。classList 属性是只读的,但你可以使用 add() 和 remove() 方法修改它。
----菜鸟教程
三.节点操作
3.1 创建元素
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
.mydiv{
height: 100px;
width: 100px;
background: deeppink;
}
</style>
</head>
<body>
<p id="p1">第一序列</p>
<script>
console.log("===>虚拟节点")
console.log("1.document.write,不推荐,没有实际形成节点");
document.write("<h1>黎明医生</h1>");//类似于Servlet PrintWrite
console.log("2.innerHTML,添加元素内容");
var p1 = document.getElementById("p1");
p1.innerHTML=p1.innerHTML+"<strong>:废土</strong>";//获取元素内容,修改,替换,之后在重新赋值
console.log("3.创建节点");
var divObj = document.createElement("div");//创建DIV标签对象
divObj.className="mydiv";
//放置哪个里面,需要告知
document.body.appendChild(divObj);//内部节点的末尾追加
//document.body.insertBefore(divObj,p1);//往哪个节点的前面添加
</script>
</body>
3.2 节点的操作
(1) 父节点操作
<div id="mydiv">
<span>span就是来修饰文本,没有任何样式,div中第一个span标签</span>
<p>
div中的第二个元素,p标签
<span>这个是p标签中的span标签</span>
</p>
<ul id="bookName">
<li>第一序列</li>
<li>黎明医生</li>
<li id="three">超凡伊始</li>
<li>黄金时代</li>
<li>北颂</li>
</ul>
</div>
<script>
let ulObj = document.getElementById("bookName");//起始点,获取标签对象
console.log(ulObj.tagName,ulObj.nodeType,"1:节点类型:标签节点",ulObj.nodeName);
console.log(ulObj.parentNode,ulObj.parentElement);//福接单:div
console.log(ulObj.parentNode.parentNode);//body
console.log(ulObj.parentNode.parentNode.parentNode);//html
console.log(ulObj.parentNode.parentNode.parentNode.parentNode);//document
console.log(ulObj.parentNode.parentNode.parentNode.parentNode.parentNode);//若不存咋子父节点,则返回null
</script>
(2)子节点操作
- 获取子节点
<div id="mydiv">
<span>span就是来修饰文本,没有任何样式,div中第一个span标签</span>
<p>
div中的第二个元素,p标签
<span>这个是p标签中的span标签</span>
</p>
<ul id="bookName">大明<li>第一序列</li><li>黎明医生</li><li id="three">超凡伊始</li><li>黄金时代</li><li>北颂</li></ul>
<!--<ul id="bookName">透视神眼<li>地府朋友圈</li><li>三界红包群</li><li id="three">冷血医生</li><li>农名工玩网游</li><li>贼行天下</li></ul>-->
</div>
<script>
let ulObj = document.getElementById("bookName");//起始点,获取标签对象
console.log("获取当前元素的子节点");
var childList = ulObj.childNodes;
console.log("childNodes空格和换行(文本)都是节点",childList.length);
for(let obj of childList){
console.log(obj.nodeType,obj.nodeName,obj.nodeValue,obj.tagName);
}
var childList = ulObj.children;
console.log("文本节点不计算在内,只能获取有标签包裹的子节点",childList.length);
</script>
- 文本节点与标签节点
<div id="mydiv">
<span>span就是来修饰文本,没有任何样式,div中第一个span标签</span>
<p>
div中的第二个元素,p标签
<span>这个是p标签中的span标签</span>
</p>
<ul id="bookName">
<li>第一序列</li>
<li>黎明医生</li>
<li id="three">超凡伊始</li>
<li>黄金时代</li>
<li>北颂</li>
</ul>
</div>
<script>
let ulObj = document.getElementById("bookName");//起始点,获取标签对象
console.log(ulObj.firstChild,"获取是文本节点",ulObj.firstChild.nodeType);
console.log(ulObj.firstElementChild,"获取是标签节点",ulObj.firstElementChild.nodeType);
console.log(ulObj.lastChild,"获取是文本节点",ulObj.lastChild.nodeType);
console.log(ulObj.lastElementChild,"获取是标签节点",ulObj.lastElementChild.nodeType);
console.log("兄弟节点");
var threeObj = document.getElementById("three");
console.log(threeObj.previousSibling,"获取是文本节点",threeObj.previousSibling.nodeType)
console.log(threeObj.previousElementSibling,"获取是标签节点",threeObj.previousElementSibling.nodeType)
console.log(threeObj.nextSibling,"获取是文本节点",threeObj.nextSibling.nodeType)
console.log(threeObj.nextElementSibling,"获取是标签节点",threeObj.nextElementSibling.nodeType)
console.log(threeObj.nextElementSibling.parentElement.firstElementChild.nextElementSibling.nextElementSibling)
</script>
案例
1.留言板
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>留言板</title>
<style>
body{
background-color: lightblue;
}
.q{
width: 960px;
margin: 200px auto;/*外边距上下为0,左右平分*/
}
.q button{
width: 80px;
height: 80px;
background-color: aliceblue;
display: inline-block;
border-radius: 50%;
text-align: center;
line-height: 80px;
text-decoration:none;
color: darkgray;
font-weight: bolder;
}
.q button:hover{
background-color: pink;
color: aqua;
}
hr {/*透明渐变水平线*/
width:80%;
margin:0 auto;
border: 0;
height: 4px;
background-image: linear-gradient(to right, rgba(0, 0, 0, 0), rgba(0, 0, 0, 0.75), rgba(0, 0, 0, 0));
}
</style>
<body>
<div class="q">
<textarea id="message" style="height: 200px;width: 300px" placeholder="请输入你的留言" autofocus required></textarea>
<hr/>
<button id="msgBtn">发送</button>
<hr/>
<ul id="result">
</ul>
</div>
<script>
let messageElement = document.getElementById("message");
let ulElement = document.getElementById("result");
document.getElementById("msgBtn").onclick = function (){
let content = messageElement.value;
if (content.trim()){//内容不为空
//1.创建元素和内容
let li = document.createElement("li");
li.innerHTML = content;
//2.追加
if (ulElement.children==0){//若留言板没有内容
ulElement.append(li);
}else {
ulElement.insertBefore(li,ulElement.firstChild);//后来的留言发送至一楼
}
//清空
messageElement.value="";
//返回光标
messageElement.focus();
}
}
</script>
</body>
</html>
2.表格操作
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>表格</title>
<body>
<table cellspacing="0" border="1" width="500">
<thead>
<tr>
<th>序号</th><th>姓名</th><th>年龄</th><th>性别</th>
</tr>
</thead>
<tbody id="result">
</tbody>
</table>
<button id="btn1">初始化数据1</button>
<button id="btn2">初始化数据2</button>
<script>
window.onload = function (){
let arr01 = [
{userName:"叶",age:19,sex:1},
{userName:"荒",age:19,sex:1},
{userName:"狗",age:66,sex:1}
];
let arr02 = [
{userName:"摇光",age:19,sex:2},
{userName:"天枢",age:19,sex:2},
{userName:"星河",age:18,sex:2}
];
/*字符串拼接*/
document.getElementById("btn1").onclick = function (){
let str = "";
for (let i = 0; i<arr01.length ; i++) {
var o = arr01[i];
str += "<tr>";
str +="<td>"+(i+1)+"</td><td>"+o.userName+"</td><td>"+o.age+"</td><td>"+(o.sex==1?"男":"女")+"</td>"
str += "</tr>";
}
document.getElementById("result").innerHTML=str;
}
/*字符串模板*/
document.getElementById("btn2").onclick = function (){
let result = document.getElementById("result");
arr02.forEach((o,index)=>{
let template = `
<tr>
<td>${index+1}</td>
<td>${o.userName}</td>
<td>${o.age}</td>
<td>${o.sex==1?"男":"女"}</td>
</tr>
`;
result.innerHTML= result.innerHTML+template;
});
}
}
</script>
</body>
</html>