节点操作
获取元素的两种方式:
- 利用DOM提供的方法获取元素
- document.getElementById()
- document.getElementByTagName()
- document.querySelector
- 等
- 逻辑性不强,繁琐
- 利用节点的层级关系获取元素
- 利用父子兄弟节点关系获取元素
- 逻辑性强,但是兼容性稍差
以上两种方式都可以获取元素节点,都会使用,但是节点操作更简单
什么是节点?
-
网页中的所有内容都是节点(标签、属性、文本、注释等),在DOM中,节点使用node来表示。
-
HTML DOM树中的所有节点均可通过JavaScript进行访问,所有HTML元素(节点)均可被修改,也可以创建或删除。
-
一般地,节点至少拥有nodeType(节点类型) 、nodeName(节点名称)和nodeValue(节点值)这三个基本属性。
- 元素节点 nodeType 为 1
- 属性节点 nodeType 为 2
- 文本节点 nodeType 为 3 (文本节点包含文字、空格、换行等)
-
实际开发中,节点操作主要操作的时元素节点
父节点操作
<div class="box">
<div class="erweima">x</div>
</div>
<script>
//1.父节点 parentNode
var erweima = document.querySelector('.erweima');
//得到的是离元素最近的父级节点 如果找不到父节点就返回 null
console.log(erweima.parentNode);
</script>
子节点操作
- firstElementChild 获取第一个子元素节点
- lastElementChild 获取最后一个子元素节点
- 这两个IE9以上才支持
实际开发中,firstchild和 lastchild包含其他节点,操作不方便,而firstElementChild和lastElementchild又有兼容性问题,那么我们如何获取第一个子元素节点或最后一个子元素节点呢?
解决方法:
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
</ul>
<script>
//DOM 提供的方法(API)获取
var ul = document.querySelector('ul');
var lis = ul.querySelectorAll('li');
//1.子节点获取 包括元素节点、文本节点等
// console.log(ul.childNodes);
// console.log(ul.childNodes[0].nodeType);
for (var i = 0; i < ul.childNodes.length; i++) {
if (ul.childNodes[i].nodeType == 1) {
//ul.childNodes[i] 是元素节点
console.log(ul.childNodes[i]);
}
}
//2. children 获取所有的子元素节点 常用
console.log(ul.children);
//1. firstChild 拿到的是第一个子节点 不管是文本节点还是元素节点
console.log(ul.firstChild);
console.log(ul.lastChild);
//2. firstElementChild 返回第一个子元素
console.log(ul.firstElementChild);
console.log(ul.lastElementChild);
//3. 实际开发的写法 既没有兼容性问题又返回第一个子元素
console.log(ul.children[0]);
console.log(ul.children[ul.children.length - 1]);//最后一个
</script>
兄弟节点
1.node.nextSibling 返回当前元素的下一个兄弟节点,找不到则返回null,也是包含所有节点
2.node.previousSibling 上一个兄弟节点
3.node.nextElementSibling 返回下一个兄弟元素节点,找不到返回null
4.node.previousElementSibling 上一个
注:3.4方法有兼容性问题,IE9以上才支持
<div>我是div</div>
<span>我是span</span>
<script>
var div = document.querySelector('div');
//下一个兄弟节点
console.log(div.nextSibling);
//上一个
console.log(div.previousSibling);
//下一个兄弟元素节点
console.log(div.nextElementSibling);
//上一个
console.log(div.previousElementSibling);
</script>
创建节点
document.createElement('tagName')
document.createElement(〉方法创建由tagName 指定的 HTML元素。因为这些元素原先不存在,是根据我们的需求动态生成的,所以我们也称为动态创建元素节点。
添加节点
1.node.appendChild(child)
//将一个节点添加到指定父节点的子节点列表末尾
2.node.insertBefore(child,指定元素)
//添加到父节点的指定子节点的前面
<ul>
<li>123</li>
</ul>
<script>
var ul = document.querySelector('ul');
//1.创建元素节点
var li = document.createElement('li');
//2.添加节点 node.appendChild(child) node 父级 child子级
ul.appendChild(li);
li.innerHTML = 'hello';
//3.添加节点 node.insertBefore()
var lili = document.createElement('li');
ul.insertBefore(lili, ul.children[0]);
lili.innerHTML = 'feliks';
</script>
留言板案例
<textarea name="" id="" cols="30" rows="10">123</textarea>
<button>submit</button>
<ul>
<li>123</li>
</ul>
<script>
var txt = document.querySelector('textarea');
var btn = document.querySelector('button');
var ul = document.querySelector('ul');
btn.onclick = function() {
if (txt.value == '') {
alert('请输入内容');
return false;
} else {
var li = document.createElement('li');
//现有li再赋值
li.innerHTML = txt.value;
// ul.appendChild(li);
ul.insertBefore(li, ul.children[0]);
//清空文本域
txt.value = '';
}
}
</script>
删除节点
node.removeChild(child)
//从DOM中删除一个子节点,返回删除的节点
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
<button>删除</button>
<script>
var btn = document.querySelector('button');
var ul = document.querySelector('ul');
// var lis = document.querySelectorAll('li');
btn.onclick = function() {
if (ul.children.length == 0) {
this.disabled = true;
} else {
ul.removeChild(ul.children[0]);
}
}
</script>
删除留言
<textarea name="" id="" cols="30" rows="10">123</textarea>
<button>submit</button>
<ul>
<!-- <li>123</li> -->
</ul>
<script>
var txt = document.querySelector('textarea');
var btn = document.querySelector('button');
var ul = document.querySelector('ul');
btn.onclick = function() {
if (txt.value == '') {
alert('请输入内容');
return false;
} else {
var li = document.createElement('li');
//现有li再赋值
li.innerHTML = txt.value + "<a href='javascript:;'>删除</a>";
// ul.appendChild(li);
ul.insertBefore(li, ul.children[0]);
//清空文本域
txt.value = '';
//删除元素
var as = document.querySelectorAll('a');
for (var i = 0; i < as.length; i++) {
as[i].onclick = function() {
//儿子让爷爷把爸爸干掉
ul.removeChild(this.parentNode);
}
}
}
}
</script>
复制节点
node.cloneNode()//浅拷贝
node.cloneNode(true)//深拷贝
//返回调用该方法的节点的一个副本
注:如果括号参数为空或为false,则是浅拷贝,只克隆节点本身,不克隆里面的子节点
<body>
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
<script>
var ul = document.querySelector('ul');
var li = ul.children[0].cloneNode(true);
ul.appendChild(li);
</script>
</body>
动态生成表格案例
<body>
<table cellspacing="0">
<thead>
<tr>
<th>姓名</th>
<th>科目</th>
<th>成绩</th>
<th>操作</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
<script>
var datas = [{
name: 'feliks',
subject: 'javascript',
score: '100'
}, {
name: 'slugger',
subject: 'javascript',
score: '98'
}, {
name: 'spiderman',
subject: 'javascript',
score: '101'
}, {
name: 'ironman',
subject: 'javascript',
score: '99'
}];
//1.往tbody里放行 有几个人就创建几行
var tbody = document.querySelector('tbody');
for (var i = 0; i < datas.length; i++) {
//2.创建tr
var tr = document.createElement('tr');
tbody.appendChild(tr);
//3.行里创建单元格 td 单元格的数量取决于每个对象的属性个数
for (var k in datas[i]) {
var td = document.createElement('td');
td.innerHTML = datas[i][k];
tr.appendChild(td);
}
//创建删除单元格
var td = document.createElement('td');
td.innerHTML = '<a href="javascropt:;">删除</a>';
tr.appendChild(td);
}
//4.删除操作 开始
var as = document.querySelectorAll('a');
for (var i = 0; i < as.length; i++) {
as[i].onclick = function() {
//点击删除当前a所在的行(a的爸爸的爸爸)
tbody.removeChild(this.parentNode.parentNode);
}
}
// for(var k in obj){
// k得到的是属性名
// obj[k] 得到的是属性值
// }
三种动态创建元素的区别
- document.write()
- element.innerHTML
- document.createElement()
区别:
- document.write()是直接将内容写入页面的内容流,但是文档流执行完毕,则它会导致页面的全部重绘
- innerHTML 是将内容写入某个DOM节点,不会导致页面全部重绘
- innerHTML 创建多个元素效率更高(不要拼接字符串,采取数组形式拼接),结构稍复杂
- createElement() 创建多个元素效率低一点点,但是结构更清晰
总结:不同浏览器下,innerHTML 效率要比 createElement 高
var btn = document.querySelector('button');
btn.onclick = function(){
document.write('<div>123</div>');
}
//这样会导致页面重绘
<div class="inner"></div>
<div class="create"></div>
<script>
//innerHTML 创建元素
var d1 = +new Date();
var inner = document.querySelector('.inner');
// for (i = 0; i < 100000; i++) {
// inner.innerHTML = '<a href="javascript:;">hello</a>'
// }//耗时962
// ==
//==数组拼接
var arr = [];
for (i = 0; i < 100000; i++) {
arr.push('<a href="javascript:;">hello</a>');
}
inner.innerHTML = arr.join('');//耗时300
var d2 = +new Date()
console.log(d2 - d1); //innerHTML耗时
//document.createElement()创建元素
var create = document.querySelector('.create');
for (i = 0; i < 100000; i++) {
var a = document.createElement('a');
create.appendChild(a);
}
var d3 = +new Date();
console.log(d3 - d2); //createElement耗时:145
</script>
DOM核心重点
文档对象模型(Document Object Model,简称DOM),是W3C组织推荐的处理可扩展标记语言(HTML或者XML)的标准编程接口。
W3C已经定义了一系列的DOM接口,通过这些DOM接口可以改变网页的内容、结构和样式。
- 对于JavaScript,为了能够使JavaScript操作HTML,JavaScript就有了一套自己的dom编程接口。
- 对于HTML,DOM 使得HTML形成一棵DOM树,包含文档、元素、节点
我们获取过来的DOM元素是一个对象(object),所以成为文档对象模型
关于DOM操作,我们主要针对元素的操作。主要有创建、增删改查、属性操作、事件操作。
创建
- document.write
- innerHTML
- createElement
增
- appendChild
- insertBefore
删
- removeChild
改
主要修改DOM的元素属性,DOM元素的内容、属性,表单的值等
- 修改元素属性:src, href, title 等
- 修改普通元素内容:innerHTML, innerText
- 修改表单元素:value, type, disable等
- 修改元素样式:style, className
查
主要获取查询DOM的元素
- DOM提供的API方法:getElementById, getElementsByTagName 古老用法不推荐
- H5提供的新方法: querySelector、querySelectorAll 提倡
- 利用节点操作获取元素:父(parentNode)、子(children)、兄弟(previousElementSibling、nextElementSibling) 提倡
属性操作
主要针对于自定义属性
- setAttribute: 设置DOM的属性值
- getAttribute: 得到DOM的属性值
- removeAttribute 移除属性
事件操作
给元素注册事件,采取 事件源.事件类型 = 事件处理程序
鼠标事件 | 触发条件 |
---|---|
onclick | 鼠标点击左键触发 |
onmouseover | 鼠标经过触发 |
… | … |