DOM document object model 文档对象模型
DOM的核心对象:是document对象
获取元素
常用获取元素的方法
getElementById
- 通过id获取
- 因为在一个页面中
id是唯一的,所以获取到的就是一个元素 - 【注】即使有两个或者两个以上相同的
id,也只会获取到第一个遇到的id
<body>
<div id="box"></div>
<script>
var box = document.getElementById('box')
console.log(box)
</script>
</body>
getElementsByClassName
- 通过标签的
class类名获取 - 在页面中
class名称不是唯一的,所以遇到相同的class会把获取到的元素放在一个伪数组里面
<body>
<ul>
<li class="newsitem">111</li>
<li class="newsitem">111</li>
<li class="newsitem">111</li>
<li class="newsitem">111</li>
<li class="newsitem">111</li>
</ul>
<script>
var items = document.getElementsByClassName("newsitem")
console.log(items)
</script>
</body>
getElementsByName
- 通过
name属性获取 - 返回一个伪数组
<body>
<ul>
<li class="newsitem">111</li>
<li class="newsitem">222</li>
<li class="newsitem" name="li">333</li>
<li class="newsitem" name="li">444</li>
<li class="newsitem">555</li>
</ul>
<script>
var items = document.getElementsByName("li")
for(var i=0;i<items.length;i++){
items[i].style.backgroundColor = "skyblue"
}
</script>
</body>
getElementsByTagName
- 通过标签获取
- 返回一个伪数组
<body>
<ul>
<li>111</li>
<li>222</li>
<li>333</li>
<li>444</li>
<li>555</li>
<p>我是p标签</p>
</ul>
<script>
// 获取页面中所有的li标签
var items = document.getElementsByTagName("li")
// 给每一个li标签添加粉色的背景颜色
for(var i=0;i<items.length;i++){
items[i].style.backgroundColor = "pink"
}
</script>
</body>
querySelector
- 只能获取到一个元素
- ()中的元素,与css样式的选择器写法一致
<body>
<div id="box1">我是id为box的盒子</div>
<div class="box2">我是class为box2的盒子</div>
<div class="box2">我是class为box2的盒子</div>
<ul>
<li>111</li>
<li>222</li>
</ul>
<script>
var box1 = document.querySelector("#box1")
box1.style.backgroundColor = "skyblue"
var box2 = document.querySelector(".box2")
box2.style.backgroundColor = "pink"
var item = document.querySelector("ul li")
item.style.backgroundColor = "orange"
</script>
</body>
【注】 这里获取不到第二个class名为box2的div标签和第二个li标签,querySelector只能获取相应名字遇到的第一个元素
querySelectorAll
- 可以获取到相应名字的所有元素
- ()中的元素,与css样式的选择器写法一致
- 返回一个伪数组
- 通过下标的方式获取到每一个元素,可以使用数组的forEach方法遍历
<body>
<div id="box">盒子1</div>
<div class="cls">盒子2</div>
<div class="cls">盒子3</div>
<div name="myname">盒子4</div>
<ul>
<li>00001</li>
<li>00002</li>
<li>00003</li>
</ul>
<ol>
<li>01</li>
<li>02</li>
</ol>
<script>
var oBox = document.querySelectorAll("#box")
oBox[0].style.backgroundColor = "skyblue"
var oCls = document.querySelectorAll(".cls")
oCls.forEach(function(item){
item.style.backgroundColor = "wheat"
})
var oList = document.querySelectorAll("ul li")
console.log(oList)
oList.forEach(function(item){
item.style.backgroundColor = "pink"
})
</script>
</body>
获取元素的定位父级
offsetParent
- offsetParent:找最近一个带有定位的父元素,
- 如果父级们都没有定位,默认找body
- 返回一个dom对象
// 封装一个函数,获取从自身到body的距离
// obj是一个形参,传入的是一个dom对象
function offset(obj) {
var o = { left: obj.offsetLeft, top: obj.offsetTop }
while (obj.offsetParent) {
// 如果obj.offsetParent是null,就说明没有定位的父元素了,
// nulL就是false, false中断循环
obj = obj.offsetParent
o.left += obj.offsetLeft
o.top += obj.offsetTop
}
return o
}
获取元素尺寸
- 就是获取元素的“占地面积”
offsetWidth 和 offsetHeight
offsetwidth:获取的是元素内容+ padding + border的宽度offsetHeight:获取的是元素内容+ padding + border的高度
clientWidth 和 clientHeight
clientwidth:获取的是元素内容+ padding的宽度clientHeight:获取的是元素内容+ padding的高度
【注】
- 获取到的尺寸是没有单位的数字
- 当元素在页面中不占位置的的时候,获取到的值是0
- 例如:元素添加了
display:none之后,获取的值就是0
- 例如:元素添加了
获取元素偏移值
offsetLeft 和 offsetTop
offsetLeft:获取的是元素偏移左边的距离offsetTop:获取的是元素偏移上边的距离- 【注】
- 偏移值的参考点:定位父级
- 定位父级:就是元素往外找遇到的第一个有定位的父级元素
- 如果父级元素都没有定位,那么偏移的距离就是相当于
body
clientLeft 和 clientTop
clientLeft:获取的是元素border-left-widthclientTop:获取的是元素border-top-width
获取可视窗口的尺寸
document.documentElement.clientWidth:获取页面可视窗口的宽度document.documentElement.clientHeight:获取页面可视窗口的高度- 【注】获取的高度和宽度都是不包含滚动条的
获取浏览器不可见区域的高度
-
简单理解:就是滚动条向上滚动了多少距离
-
兼容写法
function getSroll(){ // 不管是否带有DTD(声明头<!DOCTYPE html>)都可以使用 // 如果不是ie9+,执行后面的判断 if(window.pageXOffset!=undefined){ return { left:window.pageXOffset, top:window.pageYOffset } } // 带有DTD // 用ocument.compatMode可以检测有没有带DTD // 带了返回CSS1Compat // 不带返回BackCompat if(document.compatMode==="CSS1Compat"){ return { left:document.documentElement.scrollLeft, top:document.documentElement.scrollTop } } // 不带DTD return { left:document.body.scrollLeft, top:document.body.scrollTop } }
操作元素
操作元素文本内容
innerHTML
- 可以获取完整的html片段,包括html中的标签
- 可以解析html中的标签
innerText
- 不能获取完整的html片段,只能获取文本信息,获取不到里面的标签
- 在innerText中书写的标签会当做字符串
value
- 适用于
input、select等自带value值的标签
操作元素类名
className
- 增删改功能都是通过直接赋值的方式
<div id="box" class="item">cxm</div>
<script>
console.log(box.className) //获取id为box盒子的类的名称
box.className = "item item1" //添加
console.log(box.className)
box.className = "item1" //删
console.log(box.className)
</script>
classList
- 会把类名放在一个数组中
- 每次只能操作一个元素
.add("类名"):增加一个类名
- 在增加之前会判断原有的
box中是否已经存在相同的类名- 如果存在就不添加,不存在就添加
- 语法:
box.classList.add("类名")
.remove("类名"):删除一个类名
- 语法:
box.classList.remove("类名")
.toggle("类名"):切换
- 简单理解:
- 假设box中有这个类名,
box.classList.toggle("类名")之后,就会移除掉这个类名 - 反之,如果box中没有这个类名,
box.classList.toggle("类名")之后,就会添加上这个类名
- 假设box中有这个类名,
.contains("类名"):包含
- 返回true和false
- 包含返回true,不包含返回false
.replace():替换
- box.classList.replace("原类名","新类名")
节点
节点分类
DOM的节点我们一般分为常用的三大类:元素节点、文本节点、属性节点
属性节点操作
- attributes:查看所有属性节点
- getAttribute(): 通过属性名获取对应的属性值
- setAttribute(): 设置属性
- removeAttribute(): 删除指定的属性
<body>
<button>查看属性</button>
<button>获取属性</button>
<button>设置属性</button>
<button>删除属性</button>
<img src="./img/con2-2.jpg" alt="">
<script>
//获取元素
var oBtns = document.querySelectorAll("button")
var oImg = document.querySelector("img")
// 查看属性 attributes
oBtns[0].onclick = function () {
console.log(oImg.attributes)
// 数组方式
// for(var i = 0;i<oImg.attributes.length;i++){
// console.log(oImg.attributes[i])
// }
// 对象方式
for (var key in oImg.attributes) {
// console.log(oImg.attributes[key])
if (oImg.attributes[key].nodeType == 2) {
console.log(oImg.attributes[key])
}
}
}
// 获取属性 getAttribute("属性名称") 返回属性的值
oBtns[1].onclick = function () {
var res = oImg.getAttribute("src")
console.log(res)
}
// 设置属性 setAttribute("属性名称","属性的值")
oBtns[2].onclick = function () {
oImg.setAttribute("src","./img/con-3.jpg")
}
// 删除属性 removeAttribute("属性名称")
oBtns[3].onclick = function () {
oImg.removeAttribute("src")
}
</script>
</body>
- 点击查看属性按钮
- 点击获取属性按钮
- 点击设置属性按钮
- 点击删除属性按钮,就把图片直接删除了
获取节点
- childNodes:所有的子一级节点
- children:所有的子一级元素节点
- firstChild:第一个节点
- firstElementChild:第一个元素节点
- lastChild:最后一个节点
- lastElementChild:最后一个元素节点
- previousSibling:上一个兄弟节点
- previousElementSibling:上一个兄弟元素节点
- nextSibling:下一个兄弟节点
- nextElementSibling:下一个兄弟元素节点
- parentNode:父节点
- parentElement:父元素节点
- attributes:所有属性节点
操作节点
- 操作:增删改查
创建节点
- createElement():创建元素节点
- createTextNode():创建文本节点
- 创建节点只是创建在了内存中,并不能再页面中显示
//创建一个div元素节点
var newEle = document.createElement('div');
//创建一个文本节点
var textNode = document.createTextNode('文字文字文字...');
插入节点
- appendChild():在父元素的最后面插入节点
- insertBefore():在谁的前面插入节点
- 语法:父元素.insertBefore(要插入的节点,在谁的前面插入)
- 如果第二个参数写
null,就会插入在父元素的最后,等价于appendChild()
- 表单中的
- insertRow() :创建行
- insertCell():创建列(也就是行里面的每一个小格子)
- deleteRow():删除行
//appendChild()
var oBox = document.getElementById('box');
var pNode = document.createElement('p'); //创建一个新元素节点<p>
oBox.appendChild(pNode); //把新元素节点<p>添加box节点的子节点末尾
//insertBefore()
//通过父节点调用, 在box之前插入一个新节点p;
//第一个参数为新节点,第二个参数为在这个元素前插入
oBox.parentNode.insertBefore(p, oBox);
删除节点
- 删除子元素:removeChild()
- 语法:父元素.removeChild(要删除元素的id或class值)
- 删除自己以及自己的子元素:remove()
- 语法:元素.remove()
//通过父节点调用, 来删除指定子节点
oBox.parentNode.removeChild(oBox)
//通过父节点调用,删除整个父元素
oBox.parentNode.remove()
替换节点
- 替换节点:replaceChild()
- 语法:父元素.replaceChild(新的节点,被替换的节点)
//通过父节点调用, 新节点p替换了旧节点div
//第一个参数为新节点, 第二个参数为旧节点
box.parentNode.replaceChild(p, oBox);
克隆节点
- 克隆节点:cloneNode()
- 语法:要克隆的元素.cloneNode()
- 浅克隆:
()里面不写:意思为false,只克隆自身,不克隆后代(也就是不克隆里面的元素)
- 深克隆:
()里写true:克隆自身以及自身的所有后代,但是不会克隆事件
//获取第一个子节点, true表示复制标签和内容 , false表示只复制标签
var box = document.getElementById('box');
Var newNode = box.firstChild.cloneNode(true);
box.appendChild(newNode); //添加到子节点列表末尾
DOM事件
一个事件的组成:
1、谁触发的事件
2、 触发的什么事件:事件类型
3、触发以后做什么:事件处理函数
初识事件
什么是事件
- js属于事件驱动编程,把‘驱动’,执行,调用通过一些交互,触发一些函数
- 事件:
- 发起 --> 执行
- 绑定事件 ---> 触发事件
- on 绑定 , emit 触发 ,off 解绑
事件的模式
- JavaScript有两种事件实现模式: 内联模式, 脚本模式.
- 【注】当一个元素上绑定了内联模式和脚本模式,只执行脚本模式
内联模式 :
- 直接在HTML标签中添加事件. 这种模型是最传统简单的一种处理事件的方法。但是这种模式中事件和HTML是混写的, 并没有将JS与HTML分离, 当代码量多了以后,对后期代码维护和扩展很不利.
<input type="button" value="按钮" onclick="alert('hello');" />
//注意: 单双引号
//执行自定义的JS函数
<input type="button"value="按钮" onclick="btnClick();" />
//注意: 内联模式调用的函数不能放到window.onload里面, 否则会找不到该函数.
脚本模式:
- 脚本模式能将JS代码和HTML代码分离, 符合代码规范.
- 使用脚本模式我们需要先获取到元素节点对象, 再针对该节点对象添加事件;
例如:
var box = document.getElementById('box');
//添加事件方式一 : 通过匿名函数,可以直接触发对应的代码 (推荐)
box.onclick = function() { //给box节点对象添加点击事件onclick
console.log('Hello world!');
};
//添加事件方式二 : 通过指定的函数名赋值的方式 来执行函数
box.onclick = func; //注意这里不能写成func()
function func() { //给box节点对象添加点击事件onclick
console.log('Hello world!');
};
事件类型
浏览器事件
- load:页面加载事件
- 特点
- dom结构加载完毕,且外部所有的资源加载完成,才触发
- 凡是带有src属性的标签都有一个load事件(img、input...)
- 特点
- unload:页面卸载事件
- 触发:
- 关闭浏览器会触发一次
- 刷新页面也会触发一次
- 触发:
- DOMContentLoaded:页面结构加载完毕就触发
- scroll:浏览器滚动的时候触发
- resize:窗口大小改变
- wheel:页面上滚轮事件
<img src="./images/1.png" alt="">
<script>
// 页面加载事件
window.onload = function(){
var endTime = new Date()
console.log("全部资源加载完毕,执行onload")
console.log("加载时间为"+((endTime-startTime)/1000))
}
// 卸载事件
window.onunload = function(){
console.log("资源卸载中....")
}
// DOMContentLoaded 页面加载完毕就触发
window.addEventListener("DOMContentLoaded",function(){
startTime=new Date()
console.log("我不需等外部资源加载完,只页面机构加载完成,就触发!")
})
// 计算加载速度
// onload - DOMContentLoaded
var startTime
// 给浏览器的可视窗口绑定滚动条事件
window.onscroll = function(){
console.log("我是窗口的滚动条事件....")
// document.documentElement.scrollTop 获取页面不可区域的高度
// document.documentElement.scrollLeft 获取页面不可区域的宽度
var top = document.documentElement.scrollTop
console.log(top)
}
// 窗口大小改变
window.onresize = function () {
var w = document.documentElement.clientWidth
if (w >= 0 && w < 400) {
document.body.style.backgroundColor = "pink"
} else if (w >= 400 && w <= 600) {
document.body.style.backgroundColor = "skyblue"
} else if (w >= 600 && w <= 800) {
document.body.style.backgroundColor = "plum"
} else if (w >= 800 && w <= 1000) {
document.body.style.backgroundColor = "orange"
} else{
document.body.style.backgroundColor = "red"
}
}
</script>
鼠标事件
- click:单击事件
- dblclick:双击事件
- mousedown:鼠标左键按下事件
- mouseup:鼠标左键抬起事件
- 【注】单击一次,触发顺序:mousedown 先于 mouseup 先于 click
- contextmenu:右键单击事件
- mousemove:鼠标移动
- 鼠标移入移出事件有两对,区别:
- mouseover 和 mouseout :在父元素上设置,在父子元素上移入移出也会触发
- 【注】触发顺序
- 【注】触发顺序
- mouseenter 和 mouseleave:在父元素上设置,在父子元素上移入移出不会触发
- mouseover 和 mouseout :在父元素上设置,在父子元素上移入移出也会触发
- mousewheel:鼠标滚轮事件
键盘事件
- 一般作用在:window、document、输入框、input
- keydown:键盘按下事件
- keyup:键盘抬起事件
- keypress:非功能键(数字,字母,符号....可以触发,电脑的功能性按钮不能触发)
表单事件
- focus:获取焦点事件
- blur:失去焦点事件
- change:表单内容改变事件
- 【注】获取焦点时的内容 != 失去焦点时的内容不一致才会触发
- input:表单内容输入事件
- 每次内容不一样就会触发
- submit:表单提交事件
- 提交的时候,会先触发事件,再触发表单的默认提交行为
- 阻止表单默认提交行为
return false
- reset:表单重置事件
- 【注】:submit 和 reset 需要绑定在form表单上使用
- onselect:输入框选中事件,并且失去焦点
事件的绑定与解绑
事件绑定
dom0
-
语法:
dom节点.on+事件类型 = function(){},例如:onclick -
将一个函数赋值给了一个事件处理属性onclick 这样的方法就是DOM0级,例如:
<button id="btn" type="button"></button> <script> var btn = document.getElementById('btn'); btn.onclick = function() { console.log('Hello World'); } btn.onclick = function() { console.log('11111'); } //点击button这个按钮后,控制台会打印11111,后面这个处理函数覆盖了前面的处理函数 </script>- 【缺点】缺点在于一个处理程序无法同时绑定多个处理函数,后面绑定的处理函数会覆盖前面绑定的处理函数
dom2
-
语法1:
dom节点.addEventListener('事件类型',处理函数,true/false) -
语法2:
dom节点.addEventListener('事件类型',处理函数,{once:true,capture:true}) -
【注】处理函数只写函数名,不加小括号
- addEventListener 第三个参数默认是冒泡,第三个参数改为ture或{capture:ture}表示捕获
<button id="btn" type="button">点我</button> <script> var btn = document.getElementById('btn'); function showFn() { alert('Hello World'); } btn.addEventListener('click', showFn); </script>
事件解绑
dom0
- 语法:
dom节点.onclick = null - 直接利用dom0的缺点,后面写的处理函数覆盖前面的处理函数,来解绑事件
<button id="btn">抽奖一次</button>
<script>
var obtn = document.getElementById("btn")
obtn.onclick = function(){
//点击抽奖之后,函数执行,控制台打印出“谢谢惠顾”,
console.log("谢谢惠顾")
//给obtn按钮的点击事件赋值为null,用来达到事件解绑的功能
this.onclick = null
}
</script>
dom2
- 语法:
dom节点.removeEventListener('事件类型',处理函数) - 【注】处理函数只写函数名,不加小括号
- addEventListener和removeEventListener的第3个参数,统一为true或false,否则移除不生效
<button id="btn">抽奖一次</button>
<script>
var obtn = document.getElementById("btn")
function fn(){
console.log("谢谢惠顾")
this.removeEventListener('click',fn)
}
obtn.addEventListener("click",fn)
</script>
事件对象
事件对象:就是触发事件的时候的一条记录信息,记录点击的位置,事件的类型,目标元素...
事件对象的兼容写法:
var e=evt || window. event
- button 监听按下了那个键
- type 事件类型
- charCode 字符编码
- keyCode 按键编码
- target 和 srcElement 目标
- target:鼠标点击的目标元素,不一定等于this
- altKey
- shiftKey
- ctrlKey
- metaKey
- clientX,clientY : client客户端
- 距离浏览器可视窗口的左上角的坐标值
- pageX,pageY : page页面
- 距离页面的左上角的坐标值
- 距离页面的左上角的坐标值
- offsetX,offsetY : offset偏移
- 距离触发元素的的左上角的坐标值
- screenX,screenY : screen屏幕
<body>
<div class="box">
<span>111111</span>
</div>
<script>
var oBox = document.querySelector(".box")
oBox.onmousedown = function (evt) {
var e = evt || window.event
// e.button需要结合onmousedown来实现
// console.log(e.button) //鼠标左键0,滚轮键1,鼠标右键2
}
window.onkeydown = function (evt) {
var e = evt || window.event
// console.log(e.key) //返回按键对应的字符
// console.log(e.keyCode) //返回按钮对应的ASCII码,字母只有大写,没有小写
}
oBox.onclick = function (evt) {
var e = evt || window.event
// console.log(e.clientX,e.clientY) //鼠标单击的位置,距离浏览器可视窗口左上角的距离
// console.log(e.pageX,e.pageY) //鼠标单击位置的位置,距离页面左上角的距离
// console.log(e.offsetX,e.offsetY) //鼠标单击位置,距离元素左上角的距离
// console.log(e.screenX,e.screenY) //鼠标单击位置,距离屏幕左上角的距离
// console.log(e.altKey) //按下alt键再单击,返回true,否则返回false
// console.log(e.shiftKey) //按下shift键再单击,返回true,否则返回false
// console.log(e.ctrlKey) //按下ctrl键再单击,返回true,否则返回false
// console.log(e.mateKey) //按下win键(田)再单击,返回true,否则返回false
}
</script>
</body>
案例:鼠标拖拽
- 案例描述:在页面可视窗口范围内,鼠标按下后,盒子跟着鼠标移动,鼠标抬起时,盒子不再移动
- 思考点:临界值的判断
<style>
*{
padding: 0px;
margin: 0px;
}
#box{
width: 100px;
height: 100px;
background: pink;
position: absolute;
}
</style>
<div id="box"></div>
<script>
var obox = document.getElementById("box")
//为obox添加鼠标按下事件
obox.addEventListener("mousedown",down)
//为obox添加鼠标抬起事件
obox.addEventListener("mouseup",up)
//鼠标按下处理函数
function down(){
//鼠标按下后:为obox添加鼠标移动事件
obox.addEventListener("mousemove",move)
}
//鼠标移动事件处理函数
function move(event){
//为x、y分别为当前距离可视窗口的宽度、高度并且减去自身元素宽高的一办
var y = event.clientY - this.offsetWidth/2
var x = event.clientX - this.offsetHeight/2
//判断临界值,不让obox跑到可视窗口之外
//判断距离上边
if(y<0){
y = 0
}
//判断左边
if(x<0){
x = 0
}
//判断右边
//右边的临界值会等于 = 浏览器可视窗口的宽度 - 元素的宽度
if(x>=document.documentElement.clientWidth-this.offsetWidth){
x=document.documentElement.clientWidth - this.offsetWidth
}
//判断下边
//下边的临界值会等于 = 浏览器可视窗口的高度 - 元素的高度
if(y>=document.documentElement.clientHeight - this.offsetHeight){
y = document.documentElement.clientHeight - this.clientY
}
obox.style.top = y + "px"
obox.style.left = x + "px"
}
//鼠标抬起处理函数
function up(){
//鼠标抬起后:删除obox的鼠标移动事件
obox.removeEventListener("mousemove",move)
}
</script>
DOM事件流
标准的dom事件流
- 标准的dom事件流分为三个阶段
- 捕获:window => document => body => 父元素 => 子元素
- 目标:子元素
- 冒泡:子元素 => 父元素 => body => document => window
- 标准的dom事件流默认情况只在冒泡阶段触发
- 按照dom2事件绑定,并进行配置,才能看到捕获的回调函数被触发 例如:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>标准的dom事件流</title>
<style>
*{
padding:0;
margin:0;
}
#outer{
width: 300px;
height: 300px;
background: pink;
overflow: hidden;
}
#center{
width: 200px;
height: 200px;
background: paleturquoise;
overflow: hidden;
margin: 50px auto;
}
#inner{
width: 100px;
height: 100px;
background: plum;
margin: 50px auto;
}
</style>
</head>
<body>
<div id="outer">
<div id="center">
<div id="inner"></div>
</div>
</div>
<script>
inner.onclick = function(){
console.log("inner")
}
center.onclick = function(){
console.log("center")
}
outer.onclick = function(){
console.log("outer")
}
document.body.onclick = function(){
console.log("docuement.body")
}
document.documentElement.onclick = function(){
console.log("docuement.documentElement")
}
document.onclick = function(){
console.log("docuemnt")
}
window.onclick = function(){
console.log("window")
}
</script>
</body>
</html>
- 当点击inner时,按标准的dom事件流分析
- 捕获:window => document => body => outer => center => inner
- 目标:inner
- 冒泡:inner => center => outer => body => document => window
- 所以点击inner时,控制台最终会输出
阻止事件冒泡
- e.stopPropagation():重点
- e.cancelBubble=true:ie写法
- 兼容写法:
// 阻止冒泡兼容写法
if (e.cancelBubble) {
e.cancelBubble = true
} else {
e.stopPropagation()
}
阻止默认行为
- 常见的默认行为:
- 表单,提交,重置行为
- a标签的跳转行为
- 图片拖拽的行为
- 右键菜单,点击鼠标右键显示菜单...
- 阻止默认行为的方式(4种)
// 阻止默认行为的四种方式
// 1.重点
return false;
// 2.了解
e.returnValue = false
// 3. 重点
e.preventDefault()
// 4.兼容写法(了解)
if (e.preventDefault) {
e.preventDefault()
} else {
e.returnValue = false
}
案例:右键自定义菜单
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
* {
padding: 0;
margin: 0;
}
li {
list-style: none;
font-size: 12px;
line-height: 20px;
padding-left: 5px;
margin-top: 2px;
}
li.active {
background: #ccc;
}
.menu {
width: 70px;
display: none;
box-shadow: 1px 1px 5px 1px #ccc;
border-radius: 5px;
overflow: hidden;
padding: 5px 0px;
position: absolute;
top: 50px;
left: 50px;
}
</style>
</head>
<body>
<div class="menu">
<li class="active">复制</li>
<li>粘贴</li>
<li>剪切</li>
<li>删除</li>
<li>查看</li>
</div>
<script>
var oMenu = document.querySelector(".menu")
document.oncontextmenu = function (e) {
// 显示菜单
oMenu.style.display = "inline-block"
// 菜单位置
// 【注】记得 + 单位
oMenu.style.top = e.clientY + "px"
oMenu.style.left = e.clientX + "px"
// 阻止事件默认行为
return false
}
// 事件委托
oMenu.onmouseover = function (e) {
if (e.target.nodeName != "LI") {
return
}
// 获取菜单中所有的li标签
var oLis = e.target.parentNode.children
// 排他思想
for (var i = 0; i < oLis.length; i++) {
oLis[i].classList.remove("active")
}
e.target.classList.add("active")
}
// 事件委托
oMenu.onclick = function (e) {
if (e.target.nodeName != "LI") {
return
}
// 弹出点击内容
alert(e.target.innerText)
// 隐藏菜单
this.style.display = "none"
}
</script>
</body>
</html>
事件委托(重点)
-
事件委托:委托给父级们,让它们执行事件,目标元素值发起
-
利用
e.target可以在父元素上控制子元素的事件处理 -
优点:
- 减少事件绑定带来的开销问题
- 可以随意给动态添加或删除的子元素绑定事件
-
缺点:代码繁琐,需要寻找目标元素target
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
li {
line-height: 40px;
}
button {
margin-left: 20px;
}
</style>
</head>
<body>
<div id="box"></div>
<script>
var arr = ["111", "222", "333", "444", "555"]
var oBox = document.querySelector("#box")
for (var i = 0; i < arr.length; i++) {
// 创建li标签
var oli = document.createElement("li")
// 把数组arr中的值依次赋值给li标签
oli.innerHTML = arr[i]
// 创建button按钮
var obutton = document.createElement("button")
// 给按钮添加文本
obutton.innerHTML = "del"
// 把按钮追加到里标签中
oli.appendChild(obutton)
// 把li标签追加到oBox中
oBox.appendChild(oli)
}
//事件委托
oBox.addEventListener("click", function (e) {
console.log(e.target.nodeName)
// 判断目标元素的节点名称是否等于BUTTON
// nodeName获取到的是大写的标签
// 如果不是BUTTON就return终止函数
if (e.target.nodeName != 'BUTTON') {
return
}
// 到这里就说明是BUTTON
// 找到目标元素的父节点,删除
e.target.parentElement.remove()
})
</script>
</body>
</html>