1.DOM
【1】定义:专门操作网页内容的一套对象和函数的总称
【2】为什么使用DOM:ES标准中只规定了js语言的核心语法,没有规定如何使用js操作网页的内容。
【3】何时:今后,只要想操作网页中的内容,只能用DOM,JQuery和框架都是对DOM的简化
【3】DOM标准:国际标准,由W3C负责制定并维护,几乎所有浏览器都兼容
2.DOM树
【1】定义:一个网页的所有内容是在浏览器内存中以树形结构保存的。
【2】为什么:树形结构是能够最直观的展现上下级包含关系的结构。而网页内容中的元素结构,也是上下级包含关系
【3】如何创建
i:只要浏览器读取到一个网页的内容,都会现在内存中创建一个唯一的树根节点对象:document
ii:浏览器扫描网页内容,每扫描到一项内容(元素、文本、属性…)就会自动创建一个新的节点对象(Node),并保存当前这一项内容的属性和值,然后将新创建的节点对象保存在DOM树上对象的位置。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YrLgKhqG-1625900469176)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20210710102912635.png)]
3.查找元素
4大类查找方式
3.1不需要查找
不需要查找就可以直接获得的元素/对象:4个
- 根节点对象:document
- html元素节点对象:document.documentElement
- head元素节点对象:document.head
- body元素节点对象:document.body
3.2按节点间关系查找
【1】定义:按照元素在DOM树中的上下级或平级关系查找其他元素
【2】何时使用:在已知一个DOM元素对象,想要找这个DOM元素对象周围附近的元素时,用节点间关系进行查找
【3】如何使用
i:节点树
1).定义:包含所有网页内容的完整树结构
2).包含:2大类关系,6个属性
①父子关系:4个属性
获取的节点对象 | 方法 | 返回值 |
---|---|---|
获得一个节点对象的父级节点对象 | 节点对象.parentNode | 返回一个节点对象 |
获得一个节点对象下所有直接子节点对象的集合 | 节点对象.childNodes | 返回类数组对象 |
获得一个对象下的第一个直接子节点对象 | 节点对象.firstChild | 返回一个节点对象 |
获得一个节点对象下的最后一个直接子节点对象 | 节点对象.lastChild | 返回一个节点对象 |
②兄弟关系:2个属性
获取的节点对象 | 方法 | 返回值 |
---|---|---|
获得一个节点对象相邻的前一个兄弟节点对象 | 节点对象.previousSibling | 返回一个节点对象 |
获得一个节点对象相邻的下一个兄弟节点对象 | 节点对象.nextSibling | 返回一个节点对象 |
3).节点树查找所存在的问题:节点树会将看不见的回车、空格等空字符也创建为节点对象,严重干扰到我们的查找结果!所以,几乎不用节点树
ii:元素树
1).定义:仅包含元素节点的树形结构
2).优点:不会有看不见的空字符的干扰。所以,将来只要按节点间关系朝招元素时,就使用元素树
3).包含:2大类关系,6个属性
①父子关系:4个属性
获取的元素对象 | 方法 | 返回值 |
---|---|---|
获得一个元素对象的父级元素对象 | 元素对象.parentElement | 返回一个元素对象 |
获得一个元素对象下所有直接子元素对象的集合 | 元素对象.children | 返回类数组对象 |
获得一个对象下的第一个直接子元素对象 | 元素对象.firstElementChild | 返回一个元素对象 |
获得一个元素对象下的最后一个直接子元素对象 | 元素对象.lastElementChild | 返回一个元素对象 |
②兄弟关系:2个属性
获取的元素对象 | 方法 | 返回值 |
---|---|---|
获得一个元素对象相邻的前一个兄弟元素对象 | 元素对象.previousElementSibling | 返回一个元素对象 |
获得一个元素对象相邻的下一个兄弟元素对象 | 元素对象.nextElementSibling | 返回一个元素对象 |
iii:示例
<body>
<span id="s1">Hello</span>
<h1>标题一</h1>
<script>
//先获得四种可直接获得的节点对象
//DOM中: console.log输出的不是对象存储结构,而是DOM树结构(节点间关系)
console.log(document);
//console.dir(xxx)才是输出一个节点对象在内存中的属性结构
console.dir(document);
console.dir(document.documentElement);
console.dir(document.head);
console.dir(document.body);
//获得body的第一个直接子元素span
// var span=document.body.firstChild
var span=document.body.firstElementChild;
console.log(span);
//获得span的下一个兄弟h1
// var h1=span.nextSibling;
var h1=span.nextElementSibling;
console.log(h1);
//获得body下所有直接子元素的集合:3个元素
// console.log(document.body.childNodes);
console.log(document.body.children);
</script>
</body>
3.3按html特征查找
4个函数
i:按id名查找一个元素
1).var 一个元素对象=document.getElementById(“id名”)
2).返回值:如果找到符合要求的元素,则只返回一个元素;如果没找到,则返回null
3).强调:.前的主语必须是document,因为只找一个元素,所以函数名中Element没有s结尾,是单数形式
ii:按标签名查找多个元素
1).var 类数组对象=任意父元素.getElementsByTagName(“标签名”)
2).返回值:如果找到符合要求的元素,就返回类数组对象;如果没找到,就返回空类数组对象:{length:0}
3).注意
①因为找到多个元素,所以返回值为类数组对象
②最好指定在一个父元素范围内查找符合要求的元素。——哟花,查找范围越小,查找越快
③因为要查找多个元素,所以函数名中的Elements以s结尾,表示复数
④不仅查找直接子元素,而且会在所有后代元素中查找符合要求的元素
⑤如果这个函数规定要返回类数组对象,那么在任何时候都会返回类数组对象,即使只找到一个元素,也会把这唯一一个元素放在类数组对象中第一个位置返回。所以,如果只找到一个符合要求的元素时,必须用[0],取出类数组对象中第一个位置保存的元素对象,才能对这个元素对象继续执行后续操作!
iii:按class名查找多个元素
1). var 类数组对象=任意父元素.getElementsByClassName(“class名”)
2).返回值:如果找到符合要求的元素,就返回类数组对象;如果没找到,就返回空类数组对象:{length:0}
3).注意
①因为找到多个元素,所以返回值为类数组对象
②最好指定在一个父元素范围内查找符合要求的元素。——哟花,查找范围越小,查找越快
③因为要查找多个元素,所以函数名中的Elements以s结尾,表示复数
④不仅查找直接子元素,而且会在所有后代元素中查找符合要求的元素
⑤如果这个函数规定要返回类数组对象,那么在任何时候都会返回类数组对象,即使只找到一个元素,也会把这唯一一个元素放在类数组对象中第一个位置返回。所以,如果只找到一个符合要求的元素时,必须用[0],取出类数组对象中第一个位置保存的元素对象,才能对这个元素对象继续执行后续操作!
iv:按name名查找多个表单元素
1).var 类数组对象=document.getElementsByName(“name名”)
2).返回值:如果找到符合要求的元素,就返回类数组对象;如果没找到,就返回空类数组对象:{length:0}
3).注意
①因为找到多个元素,所以返回值为类数组对象
②最好指定在一个父元素范围内查找符合要求的元素。——哟花,查找范围越小,查找越快
③因为要查找多个元素,所以函数名中的Elements以s结尾,表示复数
④如果这个函数规定要返回类数组对象,那么在任何时候都会返回类数组对象,即使只找到一个元素,也会把这唯一一个元素放在类数组对象中第一个位置返回。所以,如果只找到一个符合要求的元素时,必须用[0],取出类数组对象中第一个位置保存的元素对象,才能对这个元素对象继续执行后续操作!
4).示例
<body>
<span>Hello World !</span>
<ul id="nav">
<li class="item parent">电影</li>
<li class="item parent">综艺
<ul>
<li class="item child active">向往的生活</li>
<li class="item child">王牌对王牌</li>
<li class="item child">青春环游记</li>
</ul>
</li>
<li class="item parent">剧集</li>
</ul>
<form>
用户名:<input name="uname"><br/>
性别:<label><input type="radio" name="sex" value="1">男</label>
<label><input type="radio" name="sex" value="0">女</label>
</form>
<script>
var ulNav=document.getElementById("nav");
console.log(ulNav);
var lis=ulNav.getElementsByTagName("li");
console.log(lis);
lis[2].style.color="orange";
var span1=document.getElementsByTagName("span")[0];
console.log(span1);
span1.style.color="red";
var lis1=ulNav.getElementsByClassName("item");
console.log(lis1);
lis1[3].style.fontSize="30px";
//查找name为sex的两个radio元素
var radios=document.getElementsByName("sex");
console.log(radios);
//查找一个name为uname的元素,为其添加阴影效果
var 姓名文本框=document.getElementsByName("uname")[0];
console.log(姓名文本框);
姓名文本框.style.boxShadow="0 0 5px red";
</script>
</body>
3.4按选择器查找
【1】何时使用:如果元素藏的很深,非常分散时,查找条件变得很复杂,都可用按选择器查找.
【2】怎样使用
i:只查找一个符合要求的元素
var 一个元素对象=任意父元素.querySelector("选择器")
ii:查找多个符合要求的元素
var 类数组对象=任意父元素.querySelectorAll("选择器")
3.5购物车示例
【1】所有DOM效果标准的4步:
- 查找所有可能触发事件的元素
- 绑定事件处理函数
- 查找要修改的元素
- 修改元素
【2】事件绑定
i:定义:浏览器自动触发的或用户手动触发的页面中内容或状态的变化
ii:问题?:默认情况下即使浏览器中发生了事件,浏览器什么也不会做!因为默认中,各个对象中的时间处理函数为null
iii:解决:绑定事件处理函数:2种方式
①手动在html中元素开始标签中绑定事件处理函数
`<元素 on事件名="事件处理函数()">`
`< script >`
function 事件处理函数(){ ... }
缺点:全手工添加,极其不便于维护
②在js中绑定
1)其实在每个元素对象身上,都有着一批名称以on开头的“事件属性”,比如:onclick, onfocus, onmouseover,…
2)当一个元素身上发生了一个事件时,浏览器会先在这个元素身上找到对应的事件属性,并执行事件属性中保存的事件处理函数
3)问题: 开局,所有元素的事件属性都为null,即使发生事件,也不知道该干什么
4). 解决: 事件绑定:
i. 什么是: 提前在元素的某个事件属性上保存一个function函数。当事件发生时,浏览器就可以找到这个函数,并自动执行!
ii. 何时: 只要希望触发事件时,可以自动执行一项提前定义好的操作时,都要先为元素绑定事件处理函数.
iii. 如何: js中
先找到要触发事件的元素
元素对象.on事件名=function(){ ... }
5). 优点: 自动绑定,可以与for循环配合批量绑定,集中绑定。
【3】示例
<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 Air 2</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");
// console.log(btns);
for(var btn of btns){
btn.onclick=function(){
// 功能一:修改span的内容
// 获取要修改的元素,本次示例中要获取当前元素button的父对象table的第二个孩子span
var span=this.parentElement.children[1];
// console.log(span);
// 获取span中现在的内容
var n=parseInt( span.innerHTML);
// 通过单击按钮的不同,改变的span中的内容也不同
// 如果当前按钮的内容是+号,就将span中该内容逐次加一
if(this.innerHTML=="+"){
n++;
}else if(n>1){//如果当前按钮不是+号,且本次按钮的值不能小于1
n--;
}
span.innerHTML=n;
//功能二:更改小计中的内容
var tbsub=this.parentElement.nextElementSibling;
var price=parseFloat( this.parentElement.previousElementSibling.innerHTML.slice(1));
// console.log(price,n);
var sub=price*n;
// console.log(sub);
tbsub.innerHTML=`¥${sub.toFixed(2)}`;
// 功能三:小计改变,总计改变
// 获取tfoot中的最后一个总计对象
var tftoatl=table.querySelector("tfoot td:last-child");
// console.log(tftoatl);
// 获取tbody中的每一行中的最后一个小计
var tds=table.querySelectorAll("tbody td:last-child");
// 设置一个变量为总计计数做准备
var total=0;
// 遍历tbody中的每行中的小计
for(var td of tds){
// 每行中的小计的值并且截取调¥符号,然后将其转为数值
total +=parseFloat( td.innerHTML.slice(1));
}
// 将total中计算出的总计的值放入到tfoot中,保留两位小数
tftoatl.innerHTML=`¥${total.toFixed(2)}`;
}
}
</script>
</body>