标签:DOM 元素 基础 li let 事件 document 节点
JS的组成
JavaSript基础
- ECMAScript
- 基本语法,为页面交互打基础。 Web APIs
- DOM
- BOM
- 是W3C组织的标准,是js的应用,为js独有的部分。
DOM
- 文档对象模型,是W3C组织推荐的处理可扩展标记语言(HTML/XHTML)的标准编程接口。
- W3C定义了一系列DOM接口,通过这些接口可以改变网页的内容、结构和样式。
- 对于HTML,dom使得html形成了一颗dom树,包含文档、元素、节点。
- 获取的DOM元素是一个对象(object),所以称为文档对象模型。
获取元素
- getElementById,根据id获取,返回Element对象
- getElementByTagName,根据标签名获取,返回以伪数组形式存储的元素对象集合,数据是动态的。
#例 获取ol标签里面的所有li标签
let ol = document.getElementByTagName('ol'); //[0l],此时得到的是一个伪数组,不能直接用,必须要指定里面一个具体对象
let li = ol[0].getElementByTagName('li');
// 或者用id方式拿到父元素ol对象
let ol = document.getElementById('ol');
let li = ol.getElementByTagName('li');
- h5 getElementByClassName,返回伪数组的集合
- h5 document.querySelector('选择器'),根据元素选择器返回第一个元素对象
<div class='box'>盒子1</div>
<div class='box'>盒子2</div>
<div id='nav'></div>
let fiestBox = document.querySelector('.box'); // 返回盒子1那个div对象
let nav = document.querySelector('#nav'); // 返回nav对象
- h5 document.querySelectorAll('选择器'),根据元素选择器返回所有元素对象
<ul class="box">
<li><img src="image/1.jpg"></li>
<li><img src="image/2.jpg"></li>
<li><img src="image/3.jpg"></li>
<li><img src="image/4.jpg"></li>
</ul>
<!--获取所有图片-->
let imgs = document.querySelector('.box').querySelectorAll('img')
- 获取body和thml元素
document.body // body
document.documentElement // html
事件
- 事件是可以呗JavaScript侦测到的行为。网页中的每一个元素都可以触发js事件。
- 事件三要素:
- 事件源(事件被触发的对象)
- 事件类型(如何触发,什么事件)
- 事件处理程序
# 三要素齐全
btn.onclick = function(){
...
}
改变元素内容
element.innerText //从起始位置到终止位置的内容,去除html标签、空格和换行
element.innerHTML //从起始位置到终止位置,包括html标签,保留空格和换行
- 操作元素案例:点击按钮将密码框type="password"切换为type="text"文本框,并可以查看密码明文。
<!--算法思路利用一个flag变量,如果是1就且换为文本,0是密码-->
<style type="text/css">
.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: 10px;
right: 30px;
width: 24px;
}
</style>
<body>
<div class="box">
<label>
<img src="image/close.png" alt="" id="eye">
</label>
<input type="password" name="" id="pwd">
</div>
</body>
<script type="text/javascript">
// 获取对象
let eye = document.getElementById('eye');
let pwd = document.getElementById('pwd');
// 注册事件
let flag = 0
eye.onclick = function () {
if(flag == 0){
pwd.type = 'text';
eye.src = 'image/open.png';
flag = 1;
}else{
pwd.type = 'password'
eye.src = 'image/close.png';
flag = 0;
}
}
</script>
节点操作
- 根据父子兄弟的层次操作,比dom操作更便捷,逻辑性更强。
- 一般的节点至少拥有nodeType(节点类型)、nodeName(节点名称)、nodeValue(节点值) 三个基本属性。实际开发中操作的通常的元素节点即标签。
- 元素节点 nodeType 为1
- 属性节点 nodeType 为2
- 文本节点 nodeType 为3(文本节点包括文字、空格、换行等)
父子节点
parentNode 父节点
- 得到离元素最近的一个父节点,如果没有返回null
<div class="box">
<span class="son">123</span>
</div>
<script type="text/javascript">
let son = document.querySelector('.son');
let father = son.parentNode;
</script>
parentNode.childNodes / parentNode.children 子节点
- parentNode.childNodes返回包含指定节点的子节点的集合,包含所有类型的节点,该集合为即时更新的集合。(不推荐使用)
- parentNode.children 返回所有的元素节点,没有文本等其他节点。
<!--获取ul里面的所有li节点-->
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
<!--使用parentNode.childNodes拿到子节点中的元素节点还需要根据nodeType进行处理-->
<!--会得到七个节点,包括4个换行的文本节点-->
let ul = document.querySelector('ul');
for(let i = 0; i < ul.childNodes.length; i++){
if(ul.childNodes[i].nodeType == 1){
}
}
<!--parentNode.children 可以直接拿到所有元素节点-->
parentNode.firstChild 第一个子节点
parentNode.lastChild 最后一个子节点
- 以上两者返回节点包含全部类型。
parentNode.firstElementChild 第一个子元素节点
parentNode.lastElementChild 最后一个子元素节点
- 以上两个返回元素节点,但不兼容IE9以下版本
- 注意:实际开发中考虑兼容性的问题,尽量使用.children取第一个或者最后一个元素节点。
- 鼠标经过出现下拉菜单的小例子
<!--当鼠标经过li里面的第二个孩子ul显示,鼠标利卡,ul隐藏-->
兄弟节点
node.nextSibling
- 返回当下元素的下一个兄弟节点,包含所有类型的节点。
node.previousSibling
- 返回当前元素上一个兄弟节点,包含所有类型的节点。
nodeElementSibling
- 返回当前元素的下一个兄弟元素节点。
node.previousElementSibling
- 返回元素的上一个兄弟元素节点。 注意:以上两个方法不兼容IE9以下版本。
- 解决兼容性问题可以自己封装一个函数
function getNextElementSibling(element) {
let el = element;
while(el = el.nextSibling){
if(el.nodeType === 1){ //判断是否属于元素节点
return el;
}
}
return null;
}
节点的增删改查
document.createElement('tagName') 创建节点
- 由tagName指定HTML元素。该元素原本不存在,根据需求动态生成,也称为动态创建元素节点。
node.appendChild(child) 添加节点
- 将一个节点添加到指定父节点的子节点列表末尾。类似于css的after伪元素。
node.insertBefore(child,指定元素)
- 将一个节点添加到父节点的指定子节点前面。
node.removeChild(child) 删除节点
留言板案例
<body>
<textarea id=""></textarea>
<button>发布</button>
<ul>
</ul>
</body>
<script type="text/javascript">
let btn = document.querySelector('button');
let text = document.querySelector('textarea');
let ul = document.querySelector('ul');
// 注册事件
btn.onclick = function () {
if(text.value == ''){
alert('请输入内容');
return;
}else{
let li = document.createElement('li');
// href='javascript:;' 阻止链接跳转
li.innerHTML = `${text.value} <a href='javascript:;'> 删除 </a>`;
// ul.appendChild(li); //最新的留言插在后面
ul.insertBefore(li,ul.children[0]); //最新的留言插在最前面
// 删除元素节点li,即它的父亲节点
let as = document.querySelctorAll('a');
<!--循环绑定事件-->
for (let i = 0; i < as.length; i++) {
as[i].onclick = function(){
// 删除的是当前a所在的父节点li,li的父节点是ul
ul.removeChild(this.parentNode);
}
}
}
}
</script>
node.cloneNode() 克隆节点(复制)
- 注意:如果括号参数为空或者false,为浅拷贝,即只克隆赋值节点本身,不克隆里面的子节点。如果括号里面为true,则为深拷贝。
三种动态创建元素的区别
document.wriite()
element.innerHTML
document.createElement()
区别
- document.write是直接将内容写入页面的内容流,但是当文档流执行完毕后再执行这句代码时,它会导致页面全部重绘。即,不能使用在任何条件后触发。
- innerHTML是将内容写入某个DOM节点,不会导致页面全部重绘。
- innerHTML采取数组形式拼接(不要直接拼接字符串)创建多个元素,效率更高,但结构稍复杂,createElement()稍低,但结构清晰。
<!--innerHTML利用数组生成多个标签,效率最高-->
let array = [];
<!--生成一千个标签放在数组里-->
for(let i = 0; i < 1000; i++){
array.push(`<divstyle="width:100px;height:2px;border:1px solidred"></div>`);
}
<!--用join变回字符串再用innerHTML生成-->
document.body.innerHTML = array.join('');
事件
注册事件
- 传统方式
- 注册事件的唯一性,即同一个元素同一个事件只能设置一个处理函数,最后注册的处理函数将会覆盖前面注册的处理函数。
- 方法监听注册方式
- w3c标准推荐方式,通过addEventListener()方法注册。IE9之前的版本用attachEvent()替代。
- 同一个元素同一个事件可以这侧多个监听器,按照注册的顺序依次执行。
eventTarget.addEventListener(type,listener[,useCapture])
- 将自订的监听器注册到eventTarget(目标对象)上,当该对象触发指定的事件时,就执行事件处理函数。该方法接收三个参数:
- type: 事件类型字符串,如click,mouseover
- listener: 事件处理函数
- useCapture: 可选参数,布尔值,默认false
btn.addEventListener('click',function(){
alert(123);
})
删除事件(解绑事件)
- 传统方式
eventTarget.onclick = null;
- 监听方式的删除/解绑
- 注意:考虑到移除时需要写函数名,所以监听事件创建时,处理函数不能使用匿名函数的方式,可以写在外面。
evenTarget.removeEventListener(type,listener[,useCapture]);
btn.addEventListener('click',fn);
function fn(){
alert('123');
}
btn.removeEventListener('click',fn);
DOM事件流
- 事件流描述的时从页面中接收事件的顺序。事件发生时会在元素节点中按照特定的顺序传播,这个传播过程即DOM事件流。
- DOM事件流有三个阶段
- 捕获阶段
- 当前目标阶段
- 冒泡阶段
使用代码验证事件流的阶段需要注意以下几点
- js代码只能执行捕获或者冒泡其中的一个阶段。
- onclick和attachEvent(ie)只能得到冒泡阶段。
- 通常使用监听的方式来验证。
- 有些事件是没有冒泡的,比如:onblur/onfocus/onmouseenter/onmouseleave
- 验证捕获阶段代码:
<html>
<body>
<div class="father">
<div class="son"></div>
</div>
</body>
<script type="text/javascript">
let son = document.querySelector('.son');
// 第三个参数设置为true则处于捕获阶段
// document -> html -> body -> father -> son
// 给son绑定事件
son.addEventListener('click',function() {
alert('son');
},true)
// 给father也绑定事件
let father = document.querySelector('.father');
father.addEventListener('click',function() {
alert('father');
},true)
// 结果:先弹出father再弹出son
</html>
- 验证冒泡阶段则把第三个参数改为false或者为空
事件对象 event
事件对象属性方法 | 说明 |
---|---|
e.target | 返回触发事件的对象(标准) |
e.srcElement | 返回触发事件的对象(非标准 ie6-8) |
e.type | 返回事件的类型 |
e.cancelBubble | 阻止冒泡(非标准ie6-8) |
e.stopPropagation() | 阻止冒泡(标准) |
e.preventDefault() | 阻止事件默认行为,如链接不跳转,表单不提交 |
e.returnValue | 同上,非标准ie6-8 |
- 有事件才会有事件对象,且不用传参,自动存在。不同的事件有不同的属性和参数。
- ie678通过window.event获取事件对象
div.onclick = function(event){}
div.addEventListener('click',function(event){})
- event.target 和 this有时候返回的数据相同,但两者不一样。前者返回的是触发事件的对象(元素),后者返回的是绑定事件的对象(元素)。
例子:阻止默认行为(事件),让链接不跳转或让提交按钮不提交。
let a = document.querySelector('a');
// event.preventDefault() 阻止事件默认行为的方法
a.addEventListener('click',function(event){
event.preventDefault();
})
// return false; 也可以阻止事件默认行为,且不存在兼容性问题,但return后面的代码不会再执行,且仅限于传统的事件注册方式,慎用。
事件委托
- 原理:不需要给每个子节点单独设置事件监听器,而是在父节点上设置监听器,然后利用冒泡原理影响设置每个子节点。
要求点击每个li都会冒出对话框,利用事件委托在ul注册事件则不用在每个li上面逐个注册。可以用event.target得到被点击的对象,对每一个不同的li做不同的处理。
<ul>
<li>123</li>
<li>123</li>
<li>123</li>
<li>123</li>
</ul>
标签:DOM,元素,基础,li,let,事件,document,节点 来源: https://www.cnblogs.com/arica/p/16490254.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。