1.DOM事件的基础知识
1、事件网址:developer.mozilla.org/zh-CN/docs/…
2.查看元素的属性(属性中onxxx就是元素拥有的事件行为)查看事件,控制台:dir(某个dom元素,如:box)
3.事件:是元素天生自带的默认行为
不论我们是否给绑定了方法,当我们操作的时候,也会把对应的事件触发
4.事件绑定:是给元素的某个行为绑定一个方法
目的是当事件行为触发的时候,会把对应的方法执行
5.获取元素的映射机制
- 1.getElementsByTagName:有映射机制
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>鼠标事件</title>
</head>
<body>
<ul id=ul_box>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
</ul>
<script>
/* 获取元素的映射机制
* getElementsByTagName:有映射机制
*/
var ul=document.getElementsByTagName("li");
var li=document.createElement('li');
ul_box.appendChild(li);
console.log(ul);
//HTMLCollection(5) [li, li, li, li, li] getElementsByTagName可以动态添加
</script>
</body>
</html>
- 2.querySelectorAll:无映射机制
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>鼠标事件</title>
</head>
<body>
<ul id=ul_box>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
</ul>
<script>
/* 获取元素的映射机制
* querySelectorAll:无映射机制
*/
var ul1=document.querySelectorAll('li');
var li=document.createElement('li');
ul_box.appendChild(li);
console.log(ul1);
//HTMLCollection(4) [li, li, li, li] querySelectorAll动态添加后不起作用
</script>
</body>
</html>
6.常用的事件行为
- 1.【鼠标事件】
- onclick:点击(移动端click被识别为单击)
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>鼠标事件</title>
<style>
#box{
width:200px;
height:200px;
background-color:pink;
}
</style>
</head>
<body>
<div id="box"></div>
<script>
var box=document.querySelector('#box');
box.onclick=function(){
console.log('单机')
}
</script>
</body>
</html>
- ondblclick:双击
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>鼠标事件</title>
<style>
#box{
width:200px;
height:200px;
background-color:pink;
}
</style>
</head>
<body>
<div id="box"></div>
<script>
var box=document.querySelector('#box');
box.ondblclick=function () {
console.log('双击');
}
</script>
</body>
</html>
- mousedown:鼠标按下
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>鼠标事件</title>
<style>
#box{
width:200px;
height:200px;
background-color:pink;
}
</style>
</head>
<body>
<div id="box"></div>
<script>
var box=document.querySelector('#box');
box.onmousedown =function () {
console.log('鼠标按下');
}
</script>
</body>
</html>
- mouseup:鼠标抬起
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>鼠标事件</title>
<style>
#box{
width:200px;
height:200px;
background-color:pink;
}
</style>
</head>
<body>
<div id="box"></div>
<script>
var box=document.querySelector('#box');
box.onmouseup =function () {
console.log('鼠标抬起');
}
</script>
</body>
</html>
- mouseover:鼠标滑过
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>鼠标事件</title>
<style>
#box{
width:200px;
height:200px;
background-color:pink;
}
</style>
</head>
<body>
<div id="box"></div>
<script>
var box=document.querySelector('#box');
box.onmouseover=function () {
console.log('鼠标滑过');
}
</script>
</body>
</html>
- mouseout:鼠标滑过
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>鼠标事件</title>
<style>
#box{
width:200px;
height:200px;
background-color:pink;
}
</style>
</head>
<body>
<div id="box"></div>
<script>
var box=document.querySelector('#box');
box.onmouseout=function () {
console.log('鼠标滑出');
}
</script>
</body>
</html>
- mouseenter:鼠标进入
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>鼠标事件</title>
<style>
#box{
width:200px;
height:200px;
background-color:pink;
}
</style>
</head>
<body>
<div id="box"></div>
<script>
var box=document.querySelector('#box');
box.onmouseenter=function () {
console.log('鼠标移入');
}
</script>
</body>
</html>
- mouseleave:鼠标离开
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>鼠标事件</title>
<style>
#box{
width:200px;
height:200px;
background-color:pink;
}
</style>
</head>
<body>
<div id="box"></div>
<script>
var box=document.querySelector('#box');
box.onmouseleave=function () {
console.log('鼠标移出');
}
</script>
</body>
</html>
- mousewheel:鼠标滚轮滚动
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>鼠标事件</title>
<style>
#box{
width:200px;
height:200px;
background-color:pink;
}
</style>
</head>
<body>
<div id="box"></div>
<script>
var box=document.querySelector('#box');
box.onmousewheel =function () {
console.log('鼠标的滚轮事件');
}
</script>
</body>
</html>
- contextmenu:鼠标右键点击
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>鼠标事件</title>
<style>
#box{
width:200px;
height:200px;
background-color:pink;
}
</style>
</head>
<body>
<div id="box"></div>
<script>
var box=document.querySelector('#box');
box.oncontextmenu =function () {
console.log(' 鼠标右击');
}
</script>
</body>
</html>
- 案例:单机和双击
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>鼠标事件</title>
<style>
#box{
width:200px;
height:200px;
background-color:pink;
}
</style>
</head>
<body>
<div id="box"></div>
<script>
var box=document.querySelector('#box');
box.onclick=function(){
//鼠标点击第一次的时候先不着急执行单机函数 等一会 看是否点击了第二下
// 若点击第二下,那就会自动执行双击:这是就要不执行单机对应的代码
clearTimeout(this.timer);
this.dbl=false;
this.timer=setTimeout(()=>{
if(this.dbl)return;
console.log('单机');//=>单机的业务代码
},300)
}
box.ondblclick=function () {
this.dbl=true;
console.log('双击');
}
</script>
</body>
</html>
- 2.【键盘事件】
绑定键盘事件的:input textarea window document.body;
- keydown 按下某个键
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>键盘事件</title>
<style>
#box{
width:200px;
height:200px;
background-color:pink;
}
</style>
</head>
<body>
<div id="box" contenteditable='true'></div>
<script>
var box=document.getElementById('box');
//方法一:
// div元素行内添加 contenteditable='true' div是一个可编辑的框
box.onkeydown=function(){
console.log('onkeydown');
}
//方法二
window.onkeydown=function(){
console.log('window keydown');
}
</script>
</body>
</html>
- keyup 抬起某个键
- keypress 长按
- 3.【移动端手指事件】
- 单手指事件模型 Touch
- ontouchstart 手指按下 手指碰到屏幕
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>事件</title>
<style>
#box{
width:200px;
height:200px;
background-color:pink;
}
</style>
</head>
<body>
<div id="box" contenteditable='true'></div>
<script>
var box=document.getElementById('box');
box.ontouchstart=function () {
console.log('start')
}
</script>
</body>
</html>
- ontouchmove 手指移动 手指在屏幕上移动
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>事件</title>
<style>
#box{
width:200px;
height:200px;
background-color:pink;
}
</style>
</head>
<body>
<div id="box" contenteditable='true'></div>
<script>
var box=document.getElementById('box');
box.ontouchmove=function () {
console.log('手指在屏幕上移动')
}
</script>
</body>
</html>
- ontouchend 手指松开 手指离开屏幕
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>事件</title>
<style>
#box{
width:200px;
height:200px;
background-color:pink;
}
</style>
</head>
<body>
<div id="box" contenteditable='true'></div>
<script>
var box=document.getElementById('box');
box.ontouchend=function () {
console.log('手指离开屏幕')
}
</script>
</body>
</html>
- touchcancel 操作取消(一般应用于非正常状态下操作结束)
- 4.【多手指事件模型Gesture】
- gesturestart
- gesturechange/gestureupdate
- gestureend
- gesturecancel
- 5.【表单元素常用事件】
- onfocus 获取焦点:光标进去input时 触发的事件
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>键盘事件</title>
</head>
<body>
<input type="text" id='inp'>
<script>
inp.onfocus=function(){
console.log('聚焦');
}
</script>
</body>
</html>
- onblur 失去焦点:光标离开input时 触发的事件
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>键盘事件</title>
</head>
<body>
<input type="text" id='inp'>
<script>
inp.onblur=function(){
console.log('失焦');
}
</script>
</body>
</html>
- onchange 内容改变:内容改变时会触发,输入完成失焦后发生改变
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>键盘事件</title>
</head>
<body>
<input type="text" id='inp'>
<script>
inp.onchange=function(){
console.log('内容改变时会触发');
}
</script>
</body>
</html>
- oninput 监听键盘操作:内容改变时会触发该函数:输入时发生改变
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>键盘事件</title>
</head>
<body>
<input type="text" id='inp'>
<script>
inp.oninput=function(){
console.log('内容改变触发函数');
}
</script>
</body>
</html>
- 6.【音视频常用事件】
- canplay:可以播放(资源没有加载完,播放中可能会卡顿)
- canplaythrough:可以播放(资源已经加载完,播放中不会卡顿)
- play 开始播放
- playing 播放中
- pause 暂停播放
- 7.【其他常用事件】
- load 资源加载完 window.onload img.onload
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>事件</title>
</head>
<body>
<div class="box">我是页面资源</div>
<script>
window.onload=function(){
console.log('我是页面资源,我已加载完成');
}
</script>
</body>
</html>
- onresize :页面窗口大小发生改变的时候触发
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>事件</title>
</head>
<body>
<script>
window.onresize=function () {
console.log('页面窗口大小发生改变');
}
</script>
</body>
</html>
- unload 资源卸载
- beforeunload 当前页面关闭之前
- error 资源加载失败
- scroll 滚动事件
- readystatechange ajax请求状态改变事件
- oncontextmenu:鼠标右键触发
- transitionend
- readystatechange
- window.onload和jq的ready事件 有什么区别?
$(document).ready(function () {
//DOM 加载完成后触发
})
//可简写成
$(function(){
})();
7.事件对象
- 1.event:事件对象,是浏览器默认传给这个函数的
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>事件对象</title>
<style>
#box{
width:200px;
height:200px;
background-color:pink;
}
</style>
</head>
<body>
<div id="box">
<button>按钮</button>
</div>
<script>
let box=document.getElementById('box');
box.onclick=function(event){
//兼容低版本浏览器
event=event||window.event;
//this是指绑定的元素
console.log(this);//box
//事件源 就是点击的哪个元素
console.log(event.target);
console.log(event);
//点击的为止 距离可视窗口的左边距
console.log(event.clientX);
//点击的为止 距离可视窗口的上边距
console.log(event.clientY);
//点击的位置 距离body的上边距
console.log(event.pageX);
// Arguments [MouseEvent, callee: ƒ, Symbol(Symbol.iterator): ƒ]
console.log(arguments);
}
</script>
</body>
</html>
- 2.event.target.value : 获取input输入的具体值
高版本浏览器可以直接使用id当做变量
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>事件对象</title>
</head>
<body>
<input type="text" id='inp'>
<script>
inp.oninput=function () {
console.log(this);//<input type="text" id='inp'>
console.log(event.target);// <input type="text" id='inp'>
console.log(event.target.value);//控制台显示具体的值
}
</script>
</body>
</html>
8.需求:当用户输入完成,敲回车键的时候alert用户输入的内容
- 1.event.code方案
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>事件对象</title>
</head>
<body>
<input type="text" id='inp'>
<script>
// + 1.event.code方案
inp.onkeydown=function(event){
console.log(event);
if(event.code.toLowerCase()=='enter'){
alert('event.target.value');
}
}
</script>
</body>
</html>
- 2.event.key方案
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>事件对象</title>
</head>
<body>
<input type="text" id='inp'>
<script>
// + 2.event.key方案
inp.onkeydown=function(event){
console.log(event);
if(event.key.toLowerCase()=='enter'){
alert('event.target.value');
}
}
</script>
</body>
</html>
9.推盒子
<!DOCTYPE html>
<html >
<head>
<meta charset="UTF-8">
<title>推盒子</title>
<style>
*{
margin:0;
padding:0;
}
#box{
width:100px;
height:100px;
background-color:pink;
}
</style>
</head>
<body>
<div id="box"></div>
<script>
//按键盘的上下左右键 控制盒子上下左右的移动
let box=document.getElementById('box');
box.top=0;
box.left=0;
window.onkeydown=function (event) {
console.log(event);
switch(event.code){
//按的上键
case 'ArrowUp':
box.top-=10;
// box.style.transform=`translate(${box.left}px,${box.top}px)`
break;
//按的下键
case 'ArrowDown':
box.top+=10;
// box.style.transform=`translate(${box.left}px,${box.top}px)`
break;
//按的是左键
case 'ArrowLeft':
box.left-=10;
// box.style.transform=`translate(${box.left}px,${box.top}px)`
break;
//按的是右键
case 'ArrowRight':
box.left+=10;
break;
}
box.style.transform=`translate(${box.left}px,${box.top}px)`
}
</script>
</body>
</html>
10.阻止默认行为
- 1.preventDefault:阻止默认行为 多数使用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>阻止默认行为</title>
<style>
*{
margin:0;
padding:0;
}
#link{
display:block;
width:100px;
height:100px;
background-color:pink;
}
#box{
width:100px;
height:200px;
background-color:blue;
position:fixed;
display:none;
}
</style>
</head>
<body>
<a href="http://baidu.com" id='link'>百度一下</a>
<div id="box"></div>
<script>
let link=document.querySelector('#link');
link.onclick=function (event) {
//1.preventDefault:阻止默认行为 多数使用
event.preventDefault();//阻止默认行为 阻止标签本身只有的特性
alert('我是弹出框');
}
</script>
</body>
</html>
- 2.return false 不推荐
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>阻止默认行为</title>
<style>
*{
margin:0;
padding:0;
}
#link{
display:block;
width:100px;
height:100px;
background-color:pink;
}
#box{
width:100px;
height:200px;
background-color:blue;
position:fixed;
display:none;
}
</style>
</head>
<body>
<a href="http://baidu.com" id='link'>百度一下</a>
<div id="box"></div>
<script>
let link=document.querySelector('#link');
link.onclick=function (event) {
alert('我是弹出框');
//2.阻止默认行为,组件标签本身具有的特性
return false;
}
</script>
</body>
</html>
- 3.阻止页面右击弹出的框
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>阻止默认行为</title>
<style>
*{
margin:0;
padding:0;
}
#link{
display:block;
width:100px;
height:100px;
background-color:pink;
}
#box{
width:100px;
height:200px;
background-color:blue;
position:fixed;
display:none;
}
</style>
</head>
<body>
<a href="http://baidu.com" id='link'>百度一下</a>
<div id="box"></div>
<script>
let link=document.querySelector('#link');
//2.阻止页面右击弹出的框
link.oncontextmenu=function(){
event.preventDefault();
console.log('我是阻止页面右击弹出的框 ');
}
</script>
</body>
</html>
- 4.右击展示小框框
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>阻止默认行为</title>
<style>
*{
margin:0;
padding:0;
}
#link{
display:block;
width:100px;
height:100px;
background-color:pink;
}
#box{
width:100px;
height:200px;
background-color:blue;
position:fixed;
display:none;
}
</style>
</head>
<body>
<a href="http://baidu.com" id='link'>百度一下</a>
<div id="box"></div>
<script>
let link=document.querySelector('#link');
//4.右击展示小框框
window.oncontextmenu=function(event){
event.preventDefault();
//鼠标右击的为止距离可以从窗口偏移量
console.log(event.clientX,event.clientY)
box.style.display='block';
box.style.left=event.clientX+'px';
box.style.top=event.clientY+'px';
}
</script>
</body>
</html>
11.input只能输入数字
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>input只能输入拼音上面数字</title>
</head>
<body>
<input type="text" id='inp'>
<script>
let inp=document.querySelector('#inp');
inp.onkeydown=function(event){
console.log(event);
if((event.keyCode >= 48 && event.keyCode<=57)||event.keyCode==8){
return true;
}
return false;
}
</script>
</body>
</html>
12.事件的传播
事件的传播,点击穿透;触发了一个元素的某个事件,他会一次吧父节点 祖父节点...最外层的节点(body或者html)
- 1.事件的传播机制:先传播 在处理 在冒泡
- 2.捕获:找到点击的元素,从外层向里找
- 3.处理:目标处理阶段找到点击的元素之后 处理以下事件对象
- 4.冒泡:找到了点击元素,也处理好了事件对象,在一层一层的从里向外执行各个对应的事件
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>事件的传播</title>
<style>
#outer{
width:400px;
height:400px;
background-color:blue;
margin:30px auto;
}
#inner{
width:200px;
height:200px;
background-color:red;
margin:100px auto;
}
#center{
width:100px;
height:100px;
background-color:green;
margin:50px auto;
}
</style>
</head>
<body>
<div id="outer">
<div id="inner">
<div id='center'></div>
</div>
</div>
<script>
outer.onclick=function(){
console.log('outer');//=>无论点击那个盒子都是输出outer
}
inner.onclick=function(){
console.log('inner');
//=>点击outer盒子,不会触发inner,点击inner盒子 及上面的盒子会触发inner
}
center.onclick=function(event){
console.log(event);//只有点击center盒子的时候触发event
console.log('center');//=>点击center盒子的时候触发的事件源是center
event.stopPropagation();//阻止冒泡 阻止外传
event.cancelBubble=true;//IE低版本
}
document.body.onclick=function(){
console.log('body');
//=>点击center盒子的时候不会触发body,因为做了event.stopPropagation();
//阻止冒泡 阻止外传,点击其他盒子的时候都会触发body
}
</script>
</body>
</html>
- 5.onmouseenter 不具备冒泡的特性
- 6.onmouseover 具备 冒泡的特征
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>事件的传播</title>
<style>
#outer{
width:400px;
height:400px;
background-color:blue;
margin:30px auto;
}
#inner{
width:200px;
height:200px;
background-color:red;
margin:100px auto;
}
#center{
width:100px;
height:100px;
background-color:green;
margin:50px auto;
}
</style>
</head>
<body>
<div id="outer">
<div id="inner">
<div id='center'></div>
</div>
</div>
<script>
// 当鼠标从outer划入inner之后:肯定会触发inner的enter和over事件,
//但是我们发现, outer之后over事件执行了,enter事件没有执行。
//这说明了 enter事件没有穿透;over事件穿透了inner的over触发传递给了outer
outer.onmouseenter=function(){
console.log('enter')
}
outer.onmouseover=function(){
console.log('over')
}
</script>
</body>
</html>
13.事件的委托
- 1.js循环的方式
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>事件的委托</title>
<style>
li{
height:50px;
border:1px solid #ccc;
margin:10px;
}
</style>
</head>
<body>
输入 ul>li*100{$} 出现提示回车
<script>
//1.js循环
let lis=document.querySelectorAll('li');
for(let i=0;i<lis.length;i++){
lis[i].onclick=function(event){
console.log(event.target);//点击页面中的每个li,控制台就会显现那个li
}
}
</script>
</body>
</html>
- 2.事件委托
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>事件的委托</title>
<style>
li{
height:50px;
border:1px solid #ccc;
margin:10px;
}
</style>
</head>
<body>
输入 ul>li*100{$} 出现提示回车
<script>
//2.事件委托
//本来是要绑定给每一个子元素的事件,我们可以绑定到父元素上
// 通过事件的冒泡结合 e.target 我们实现要的效果,避免了给每一个元素的绑定事件
let ul=document.querySelector('li');
ul.onclick=function(event){
//点击每一个li的时候都会触发ul的点击事件 因为事件的冒泡机制;
console.log(event.target)
}
</script>
</body>
14.多级菜单
- 1.JQ版
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>多级菜单</title>
<style>
.hide{
display: none;
}
</style>
</head>
<body>
<!--
给 ul 绑定点击事件; 通过事件委托的方式 查出点击元素,然后控制点击元素的兄弟元素
加不加hide类名即可
-->
<ul id='box'>
<li>
<span>一级菜单1</span>
<ul>
<li>
<span>二级菜单1</span>
<ul>
<li>
<span>三级菜单1</span>
</li>
<li>
<span>三级菜单2</span>
<ul>
<li>
<span>四级菜单1</span>
</li>
</ul>
</li>
</ul>
</li>
<li>
<span>二级菜单2</span>
<ul>
<li>
<span>三级菜单1</span>
</li>
<li>
<span>三级菜单2</span>
</li>
</ul>
</li>
</ul>
</li>
<li>
<span>一级菜单2</span>
<ul>
<li>
<span>二级菜单1</span>
<ul>
<li>
<span>三级菜单1</span>
</li>
<li>
<span>三级菜单2</span>
<ul>
<li>
<span>四级菜单1</span>
</li>
</ul>
</li>
</ul>
</li>
<li>
<span>二级菜单2</span>
<ul>
<li>
<span>三级菜单1</span>
</li>
<li>
<span>三级菜单2</span>
</li>
</ul>
</li>
</ul>
</li>
<li>
<span>一级菜单3</span>
<ul>
<li>
<span>二级菜单1</span>
<ul>
<li>
<span>三级菜单1</span>
</li>
<li>
<span>三级菜单2</span>
<ul>
<li>
<span>四级菜单1</span>
</li>
</ul>
</li>
</ul>
</li>
<li>
<span>二级菜单2</span>
<ul>
<li>
<span>三级菜单1</span>
</li>
<li>
<span>三级菜单2</span>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</body>
</html>
<!-- 1.JQ版 -->
<script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script>
<script>
$("#box").on('click',function(e){
var $tar = $(e.target);
if($tar[0].nodeName.toLowerCase() === 'span'){
let $next = $tar.siblings('ul');
$next.toggleClass('hide');
if($next.hasClass('hide')){
$next.find('ul').addClass('hide');
// $next.children('ul');
// find 是所有后代 children是获取子代
}
}
});
</script>
- 2.js版
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style>
.hide{
display: none;
}
</style>
</head>
<body>
<!--
给 ul 绑定点击事件; 通过事件委托的方式 查出点击元素,然后控制点击元素的兄弟元素
加不加hide类名即可
-->
<ul id='box'>
<li>
<span>一级菜单1</span>
<ul>
<li>
<span>二级菜单1</span>
<ul>
<li>
<span>三级菜单1</span>
</li>
<li>
<span>三级菜单2</span>
<ul>
<li>
<span>四级菜单1</span>
</li>
</ul>
</li>
</ul>
</li>
<li>
<span>二级菜单2</span>
<ul>
<li>
<span>三级菜单1</span>
</li>
<li>
<span>三级菜单2</span>
</li>
</ul>
</li>
</ul>
</li>
<li>
<span>一级菜单2</span>
<ul>
<li>
<span>二级菜单1</span>
<ul>
<li>
<span>三级菜单1</span>
</li>
<li>
<span>三级菜单2</span>
<ul>
<li>
<span>四级菜单1</span>
</li>
</ul>
</li>
</ul>
</li>
<li>
<span>二级菜单2</span>
<ul>
<li>
<span>三级菜单1</span>
</li>
<li>
<span>三级菜单2</span>
</li>
</ul>
</li>
</ul>
</li>
<li>
<span>一级菜单3</span>
<ul>
<li>
<span>二级菜单1</span>
<ul>
<li>
<span>三级菜单1</span>
</li>
<li>
<span>三级菜单2</span>
<ul>
<li>
<span>四级菜单1</span>
</li>
</ul>
</li>
</ul>
</li>
<li>
<span>二级菜单2</span>
<ul>
<li>
<span>三级菜单1</span>
</li>
<li>
<span>三级菜单2</span>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</body>
</html>
<script>
/*
box.classList
add(类名) 新增类名
remove(类名) 删除类名
toggle(类名) 切换类名 有这个类名就删除 没有这个类名就添加
contains(类名) 查看是否包含这个类名; 包含 就是true 不包含就是false
*/
let box = document.querySelector('#box');
box.onclick = function(e){
e = e || window.event;
let tar = e.target || e.srcElement;// 容错机制
if(tar.nodeName.toLowerCase() == 'span'){
// 证明点击的是 span
let next = tar.nextElementSibling;// 获取点击元素的弟弟元素节点
// 判断弟弟元素节点是否存在, 存在的话 在判断是否是ul
if(next && next.nodeName.toLowerCase() == 'ul'){
next.classList.toggle('hide');
// 当 这个 ul被遮住之后 要让所有的后代都遮住
// 就是 判断 这个ul 有没有 hide; 有hide 就让所有的后代 ul 都加上hide
if(next.classList.contains('hide')){
let uls = next.getElementsByTagName('ul');
for(let i = 0; i < uls.length; i++){
uls[i].classList.add('hide')
}
}
}
}
}
</script>
15.鼠标跟随显示图片
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>鼠标跟随显示图片</title>
<style>
.lit_imgbox{
width: 200px;
height: 200px;
overflow: hidden;
margin: 20px;
}
.lit_imgbox img{
width: 100%;
height: 100%;
}
#big_imgbox{
display: none;
width: 400px;
height: 400px;
position: fixed;
left: 0;
top: 0;
}
#big_imgbox img{
width: 100%;
height: 100%;
}
</style>
</head>
<body>
<!--
$.extend({}) // 扩展到JQ自己身上 $.
$.fn.extend({}) // 扩展到JQ的原型上 $().
$.extend = $.fn.extend = function(){}
-->
<div class="lit_imgbox">
<img src="https://dss1.bdstatic.com/70cFvXSh_Q1YnxGkpoWK1HF6hhy/it/u=28057649,500045150&fm=26&gp=0.jpg" alt="">
</div>
<div class="lit_imgbox">
<img src="https://dss0.bdstatic.com/-0U0bnSm1A5BphGlnYG/tam-ogel/0176cb5938268a444a09a472232a3ee9_259_194.jpg" alt="">
</div>
<div class="lit_imgbox">
<img src="https://dss0.baidu.com/6ONWsjip0QIZ8tyhnq/it/u=184164756,4275686560&fm=173&app=49&f=JPEG?w=312&h=208&s=D5A5FC5852F3B06F1A085B1D0300C0C4" alt="">
</div>
<div class="lit_imgbox">
<img src="https://dss0.baidu.com/6ONWsjip0QIZ8tyhnq/it/u=3124272852,4033309804&fm=173&app=49&f=JPEG?w=312&h=208&s=F9A01B7004BA5396820051E90300A020" alt="">
</div>
<div id="big_imgbox">
<img src="https://dknet.gitee.io/daily_work/%E6%9D%8E%E6%99%93%E5%A8%9F/images/%E4%B8%8B%E8%BD%BD.jfif" alt="">
</div>
</body>
</html><script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script>
<!-- 1.JQ版 -->
<script>
let $lit = $('.lit_imgbox'),
$big = $('#big_imgbox');
$lit.on('mouseenter',function(){
$big.show();
// 当划过小图的时候 要获取到小图的图片地址
this.img = $(this).find('img').attr('src');
console.log(this.img)
// 获取到小图的地址之后 再赋给 大图
$big.find('img').attr('src',this.img)
})
$lit.on('mousemove',function(e){
$big.css({
transform:`translate(${e.clientX+5}px,${e.clientY+5}px)`
})
})
$lit.on('mouseleave',function(){
$big.hide()
})
</script>
16.DOM2级事件
- 1.onclick
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>DOM2级事件</title>
<style>
#box{
width:100px;
height:100px;
background-color:pink;
}
#outer{
width:400px;
height:400px;
background-color:blue;
margin:30px auto;
}
#inner{
width:200px;
height:200px;
background-color:red;
margin:100px auto;
}
#center{
width:100px;
height:100px;
background-color:green;
margin:50px auto;
}
</style>
</head>
<body>
<div id="box"></div>
<script>
let box=document.querySelector('#box');
//1.onclick
box.onclick=function(){
console.log('我是第一次输入内容');//点击盒子控制台提示
};
</script>
</body>
</html>
- 2.添加事件:元素.addEventListener(事件类型,回调函数,布尔类型(可省略))
- 1.同一个事件类型 可以绑定多个回调函数
- 2.第三个参数 bol默认是false;false代表函数要在冒泡阶段执行;true代表函数要在捕获阶段执行
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>DOM2级事件</title>
<style>
#box{
width:100px;
height:100px;
background-color:pink;
}
</style>
</head>
<body>
<div id="box"></div>
<script>
let fn=function(){
console.log('我是第二次输出内容')
}
box.addEventListener("click",fn);
box.addEventListener("click",function(){
console.log('我是第三次输出内容')
});
</script>
</body>
</html>
- 3.移除事件:元素.removeEventListener(事件类型,回调函数,bol(可省略))
- 移除事件是 要保证移除的哪个事件对应函数地址是存在的,不是一个新地址
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>DOM2级事件</title>
<style>
#box{
width:100px;
height:100px;
background-color:pink;
}
</style>
</head>
<body>
<div id="box"></div>
<script>
let fn=function(){
console.log('我是第二次输出内容')
}
box.addEventListener("click",fn);
box.addEventListener("click",function(){
console.log('我是第三次输出内容')
});
box.removeEventListener("click",fn);
</script>
</body>
</html>
- 3.DOM2级语法
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>DOM2级事件</title>
<style>
#outer{
width:400px;
height:400px;
background-color:blue;
margin:30px auto;
}
#inner{
width:200px;
height:200px;
background-color:red;
margin:100px auto;
}
#center{
width:100px;
height:100px;
background-color:green;
margin:50px auto;
}
</style>
</head>
<body>
<div id="outer">
<div id="inner">
<div id='center'></div>
</div>
</div>
<script>
outer.addEventListener('click',function(){
console.log('outer');//点击outer 触发outer盒子
},true);
inner.addEventListener('click',function(){
console.log('inner');//点击inner 触发inner和子和下面的outer盒子
},true);
center.addEventListener('click',function(){
console.log('center');//点击center 触发center盒子本身和outer和inner
},true);
</script>
</body>
</html>
- 4.JQ的事件绑定 利用的是DOM2级事件绑定
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>DOM2级事件</title>
<style>
#box{
width:100px;
height:100px;
background-color:pink;
}
</style>
</head>
<body>
<div id="box"></div>
<script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script>
<script>
// 3.JQ的事件绑定 利用的是DOM2级事件绑定
let $box=$('#box');
$box.on('click',function(){
console.log('我是jq1,我是默认二级事件绑定')
});
let fn=function(){
console.log('我是jq2,我是默认二级事件绑定')
};
$box.on('click',fn);//绑定
$box.off('click',fn);//解除
</script>
</body>
</html>
17 放大镜
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>放大镜</title>
<style>
*{
margin:0;
padding:0;
}
#mag{
margin:0px auto;
}
.minBox{
width:200px;
height:200px;
border:1px solid #ccc;
}
.minBox .mask{
position:absolute;
left:8px;
top:20px;
cursor: move;
width:100px;
height:100px;
background:rgba(0,0,0,0.5);
}
.minBox img{
width:100%;
height:100%;
}
.bigBox{
width:300px;
height:300px;
border:1px solid #ccc;
position:relative;
left:201px;
top:-200px;
overflow: hidden;
display:none;
}
.bigBox img{
width:600px;
height:600px;
position: absolute;
}
</style>
</head>
<body>
<div id="mag">
<div class="minBox">
<div class='mask'></div>
<img src="https://img11.360buyimg.com/n1/s450x450_jfs/t1/101657/4/19179/137400/5e9ade96E47d86e71/0cf6e05c9b7d4360.jpg" alt="">
</div>
<div class="bigBox">
<img src="https://img14.360buyimg.com/n0/jfs/t1/101657/4/19179/137400/5e9ade96E47d86e71/0cf6e05c9b7d4360.jpg" alt="">
</div>
</div>
<script>
//宽度比: 蒙层/小图=大盒子/大图片 100/200=300
let min=document.querySelector('.minBox');
let mask=document.querySelector('.mask');
let big=document.querySelector('.bigBox');
let bigImg=big.querySelector('img');
min.onmouseenter=function(){
//1.滑入小盒子的时候,要让 蒙层和大盒子显示出来
mask.style.display='block';
big.style.display='block';
}
min.onmouseleave=function(){
//2.离开小盒子 要让蒙层和小盒子隐藏
mask.style.display='none';
big.style.display='none';
}
//鼠标在小盒子上移动时,要让蒙层随着移动
min.onmousemove=function(event){
//由于 蒙层时相对于小盒子 进行移动的
//想实现蒙层跟着鼠标移动 需要算出 鼠标 距离 小盒子的偏移量
//把这个偏移量设置给 蒙层 就正好时蒙层在盒子上的位置
//偏移量:用鼠标到body的偏移-盒子到body的偏移
//偏移量:用鼠标到可是窗口的偏移-盒子到可视窗口的 偏移
console.log(event.pageX,event.clientX);
let curO=offset(this);//算出this(min)小盒子到body偏移量
let left=event.pageX-curO.left-mask.clientWidth/2,
top=event.pageY-curO.top-mask.clientHeight/2;//left top分别对应蒙层在小盒子中的偏移量
// 考虑边界问题?
// 向左走 最多走到0 不能是负数;向右走 最多到 小盒子款-蒙层宽;
// 向上 最多走到0 不能为负数;向下最多到 小盒子高 -蒙层高
let maxLeft=this.clientWidth-mask.clientWidth,
maxTop=this.clientHeight-mask.clientHeight;//右下边界就算出来了;
// left 的左边界是0; 右边界是maxL
// top 的上边界是0; 下边界是maxT
// 超出边界 做什么?
// 超出边界 就让对应的值 等于边界即可
left=left<0?0:(left>maxLeft?maxLeft:left);
if(top<0){
top=0
}else if(top>maxTop){
top=maxTop
}else{
top=top;
}
mask.style.left=left+"px";
mask.style.top=top+"px";
let n=big.clientHeight/mask.clientHeight;
bigImg.style.left=-left*3+'px';
bigImg.style.top=-top*3+'px';
}
function offset(element){
//可以获取到element这个元素到body的偏移量
let left=element.offsetLeft,
top=element.offsetTop;//获取当前元素到父级参照物的偏移量
let parent=element.offsetParent;//获取父级参照物
while(parent){
// 若父级参照物存在
left+=(parent.clientLeft||0)+parent.offsetLeft;
top+=(parent.clientTop||0)+parent.offsetTop;
parent=parent.offsetParent;
}
return{
left,
top
}
}
</script>
<script>
new mag('#mag');
new mag('#mag2');
new mag('#mag3');
</script>
</body>
</html>
18.事件委托应用
- 1.增加删除新闻 jq实现 非事件委托
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>事件委托的应用场景</title>
<link rel="stylesheet" href="reset.min.css">
<style>
.box{
font-size:16px;
margin:20px;
}
.newsList{
margin-bottom:10px;
}
.newsList li{
line-height:30px;
border-bottom:1px solid #ccc;
}
</style>
</head>
<body>
<div class="box">
<ul class="newsList">
<li>我是新闻1
<a href="javascript:;">删除</a>
</li>
<li>我是新闻2
<a href="javascript:;">删除</a>
</li>
<li>我是新闻3
<a href="javascript:;">删除</a>
</li>
<li>我是新闻4
<a href="javascript:;">删除</a>
</li>
<li>我是新闻5
<a href="javascript:;">删除</a>
</li>
</ul>
<a href="javascript:;" id='addNews'>新增</a>
</div>
<script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script>
<!-- 1.jq实现 非事件委托-->
<script>
let $addNews=$('#addNews'),
$newsList=$('.newsList'),
$links=$newsList.find('a');
count=5;
//只给默认的五个A点击事件行为绑定方法
$links.click(function(){
//this:当前点击的删除的按钮A
$(this).parent().remove();
})
$addNews.click(function(){
let str=``;
for(let i=0;i<5;i++){
str+=`<li>我是新闻${++count}
<a href="javascript:;">删除</a>
</li>`;
}
$newsList.append(str);
//新增的删除按钮,没有绑定点击事件,需要在每一次新增完成,重新获取到所有的a,给其点击事件行为绑定方法
$links=$newsList.find('a');
$links.click(function(){
//this:当前点击的删除的按钮A
$(this).parent().remove();
})
})
</script>
</body>
</html>
- 2.jq 事件委托
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>事件委托的应用场景</title>
<link rel="stylesheet" href="reset.min.css">
<style>
.box{
font-size:16px;
margin:20px;
}
.newsList{
margin-bottom:10px;
}
.newsList li{
line-height:30px;
border-bottom:1px solid #ccc;
}
</style>
</head>
<body>
<div class="box">
<ul class="newsList">
<li>我是新闻1
<a href="javascript:;">删除</a>
</li>
<li>我是新闻2
<a href="javascript:;">删除</a>
</li>
<li>我是新闻3
<a href="javascript:;">删除</a>
</li>
<li>我是新闻4
<a href="javascript:;">删除</a>
</li>
<li>我是新闻5
<a href="javascript:;">删除</a>
</li>
</ul>
<a href="javascript:;" id='addNews'>新增</a>
</div>
<script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script>
<!-- 2.事件委托实现 -->
<script>
//给动态绑定渲染的元素的每个事件行为绑定方法=>事件委托
let $addNews=$('#addNews'),
$newsList=$('.newsList');
count=5;
$newsList.click(function (event) {
let target=event.target,
$target=$(target);
if(target.tagName==='A'){
$target.parent().remove();
}
});
$addNews.click(function(){
let str=``;
for(let i=0;i<5;i++){
str+=`<li>我是新闻${++count}
<a href="javascript:;">删除</a>
</li>`;
}
$newsList.append(str);
})
</script>
</body>
</html>
- 3.购物车的css实现
<!DOCTYPE html>
<html >
<head>
<meta charset="UTF-8">
<title>事件委托应用场景2</title>
<link rel="stylesheet" href="reset.min.css">
<style>
.shopBox{
position:relative;
box-sizing:border-box;
display:block;
width:100px;
height:35px;
line-height:35px;
text-align:35px;
background:pink;
color:#000;
}
.shopBox .detail{
display:none;
position:absolute;
top:35px;
left:0;
width:300px;
height:100px;
text-align:center;
background:blue;
}
.shopBox:hover .detail{
display:block;
}
</style>
</head>
<body>
<!-- //不基于js实现鼠标滑过展示详情,鼠标在按钮和详情区'展示详情',
//只要离开这两个区域,详情区域就'隐藏'
//+ 1.详情区域必须要是当前盒子的后代元素
// + 2.基于css3中的:hover即可实现 -->
<a href="javascript:;" class='shopBox'>
购物车
<div class='detail'>暂无购物车信息</div>
</a>
</body>
</html>
- 4.购物车的事件委托实现
<!DOCTYPE html>
<html >
<head>
<meta charset="UTF-8">
<title>事件委托应用场景2</title>
<link rel="stylesheet" href="reset.min.css">
<style>
html,body{
min-height:100%;
background:#f6f7fb;
}
.shopBox{
position:relative;
box-sizing:border-box;
display:block;
width:100px;
height:35px;
line-height:35px;
text-align:35px;
background:pink;
color:#000;
}
.detail{
display:none;
width:300px;
height:100px;
text-align:center;
background:blue;
}
</style>
</head>
<body>
<a href="javascript:;" class='shopBox'>
购物车
</a>
<div class='detail'>暂无购物车信息</div>
<script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script>
<!-- 事件委托 -->
<script>
let $detail=$('.detail');
$(document).click(function(ev){
let target=ev.target,
$target=$(target);
if($target.hasClass('shopBox')){
$detail.slideToggle(300);
return;
}
$detail.slideUp(300);
});
$detail.click(function(ev){
//点击detail的时候,我们阻止冒泡传播也就不会在把上面的方法执行了
ev.stopPropagation();
})
</script>
</body>
</html>
- 5.购物车 非事件委托
<!DOCTYPE html>
<html >
<head>
<meta charset="UTF-8">
<title>事件委托应用场景2</title>
<link rel="stylesheet" href="reset.min.css">
<style>
html,body{
min-height:100%;
background:#f6f7fb;
}
.shopBox{
position:relative;
box-sizing:border-box;
display:block;
width:100px;
height:35px;
line-height:35px;
text-align:35px;
background:pink;
color:#000;
}
.detail{
display:none;
width:300px;
height:100px;
text-align:center;
background:blue;
}
</style>
</head>
<body>
<a href="javascript:;" class='shopBox'>
购物车
</a>
<div class='detail'>暂无购物车信息</div>
<script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script>
<!-- 非事件委托:方法一 -->
<script>
//点击购物车,按照详情区域现在的状态控制显示隐藏,
//点击详情区域中的信息,不做任何的处理(也就是不隐藏),
//但是点击除这两个区域以外的"任何区域",都让详情消失=>这种除啥啥事的事件源以外的其他事件源,
//操作的时候统一做什么事情的时候,基本上都要用事件委托来解决
let $detail=$('.detail');
$(document).click(function(ev){
let target=ev.target,
$target=$(target);
if($target.hasClass('shopBox')){
//点击的是购物车按钮;toggle/slideToggle是jq自带的方法,
//可以控制元素显示隐藏的切换,对应的是show/hide(slideDown/slideUp)
$detail.slideToggle(300);
return;
}
if($target.hasClass('detail')){
//爱你寄的是detail则啥都不处理
return;
}
//以上条件不成立,则让detail小时
$detail.slideUp(300);
})
</script>
</body>
</html>