文章目录
MDN文档链接: https://developer.mozilla.org/zh-CN/docs/Web/API

DOM基础
DOM 简介
文档对象模型(Document Object Model,简称 DOM),是 W3C 组织推荐的处理可扩展标记语言(HTML或者XML)的标准编程接口。 W3C 已经定义了一系列的 DOM 接口,通过这些 DOM 接口可以改变网页的内容、结构和样式。
获取元素
因为文档页面从上往下加载,所以先要写标签,script要写到标签下面
根据 ID 获取
getElementById() 方法,返回带有 ID 的元素对象。
document.getElementById(‘id’);
console.dir() 可以打印我们获取的元素对象,更好的查看对象里面的属性和方法。
<body>
<div id="time">2022-8-30</div>
<script>
// 因为文档页面从上往下加载,所以先要写标签,script要写到标签下面
var timer=document.getElementById('time');
console.log(timer);
console.log(typeof timer);//返回的是一个对象
console.dir(timer);
</script>
</body>
根据标签名获取
使用 getElementsByTagName() 方法可以返回带有指定标签名的对象的集合。
document.getElementsByTagName(‘标签名’);
注意:
- 因为得到的是一个对象的集合,所以我们想要操作里面的元素就需要遍历。
- 得到元素对象是动态的
- 返回的是元素对象的伪数组,如果页面中没有该元素,返回的是空的伪数组。
<body>
<ul>
<li>这是一个标签1</li>
<li>这是一个标签2</li>
<li>这是一个标签3</li>
<li>这是一个标签4</li>
<li>这是一个标签5</li>
</ul>
<script>
//返回的是元素对象的伪数组
var lis=document.getElementsByTagName('li');
console.log(lis);
console.log(lis[0]);
//遍历元素
for(var i=0;i<lis.length;i++){
console.log(lis[i]);
}
</script>
</body>
获取父元素内部的指定标签名的子元素
注意:父元素必须是一个指定的元素
<body>
<ul>
<li>这是一个标签1</li>
<li>这是一个标签2</li>
<li>这是一个标签3</li>
<li>这是一个标签4</li>
<li>这是一个标签5</li>
</ul>
<ol id="ol">
<li>1234567</li>
<li>1234567</li>
<li>1234567</li>
</ol>
<script>
var ol=document.getElementsByTagName('ol');
console.log(ol[0].getElementsByTagName('li'));//必须指明哪一个元素
var ol1=document.getElementById('ol');
console.log(ol1.getElementsByTagName('li'));
</script>
</body>
- document.getElementsByClassName(‘类名’);根据类名返回元素对象集合
- document.querySelector(‘选择器’); 根据指定选择器返回第一个元素对象
根据类名class选择,加 “ . ” ,根据id选择,加 “ # ” ,根据标签选择,不用加 - document.querySelectorAll(‘选择器’); 根据指定选择器返回所有对象
<body>
<div class="box">盒子</div>
<div class="box">盒子</div>
<div id="nav">
<ul>
<li>产品</li>
<li>首页</li>
</ul>
</div>
<script>
// getElementsByClassName(‘类名’) 根据类名返回元素对象集合
var boxes=document.getElementsByClassName('box');
console.log(boxes);
// document.querySelector('选择器') 根据指定选择器返回第一个元素对象
var firstBox=document.querySelector('.box');//根据class选择
console.log(firstBox);
var nav=document.querySelector('#nav');//根据id选择
console.log(nav);
var li=document.querySelector('li');//根据标签选择
console.log(li);
// document.querySelectorAll('选择器') 根据指定选择器返回
var allBox=document.querySelectorAll('.box');
console.log(allBox);
</script>
</body>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
// 获取body元素
var bodyEle=document.body;
console.log(bodyEle);
console.dir(bodyEle);
// 获取html元素
var htmlEle=document.documentElement;
console.log(htmlEle);
</script>
</body>
</html>
事件基础
事件三要素
- 事件源 (谁)
- 事件类型 (什么事件)
- 事件处理程序 (做啥)
示例:
<body>
<!-- 点击一个按钮,弹出对话框 -->
<button id="btn">唐伯虎</button>
<script>
var btn=document.getElementById('btn');//获取事件源
// 事件类型,如何触发事件
// 事件处理程序 通过一个函数赋值的方式完成
btn.onclick=function(){
alert('点秋香');
}
</script>
</body>
执行事件的步骤
- 获取事件源
- 注册事件(绑定事件)
- 添加事件处理程序(采取函数赋值形式)
示例:
<body>
<div>123</div>
<script>
var div=document.querySelector('div');//获取事件源
//注册事件,添加事件处理程序
div.onclick=function(){
console.log('我被选中了');
}
</script>
</body>
操作元素
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
div,
p {
width: 300px;
height: 30px;
line-height: 30px;
color: #fff;
background-color: blue;
}
</style>
</head>
<body>
<button>显示当前系统时间</button>
<div>某个时间</div>
<p>1123</p>
<script>
var btn=document.querySelector('button');
var div=document.querySelector('div');
btn.onclick=function(){
div.innerText= getDate();
}
function getDate() {
var date=new Date();
var year=date.getFullYear();
var month=date.getMonth();
var dates=date.getDate();
var day=date.getDay();
var arr=['星期日','星期一','星期二','星期三','星期四','星期五','星期六'];
return '今天是:'+year+'年'+month+'月'+dates+'日,本周'+arr[day];
}
var p=document.querySelector('p');
p.innerText=getDate();//可以不用添加事件
</script>
</body>
</html>
innerText 和 innerHTML 的区别
- innerText不识别 html标签;innerHTML 可以识别
<body>
<div></div>
<script>
var div=document.querySelector('div');
div.innerText='<strong>今天是:</strong>2019';
div.innerHTML='<strong>今天是:</strong>2019';
</script>
</body>
2. 两个属性都可以可以获取元素里的内容,innerText 会去除换行和空格;innerHTML 保留空格和换行。
<body>
<div></div>
<p>
我是文字
<span>
123
</span>
</p>
<script>
// 可以获取元素里的内容
var p=document.querySelector('p');
console.log(p.innerText);
console.log(p.innerHTML);
</script>
</body>
格式:元素.属性=赋值;
案例:点击切换图片
<body>
<button id="ldh">刘德华</button>
<button id="zxy">张学友</button> <br>
<img src="images/ldh.jpg" alt="" title="刘德华">
<script>
// 修改元素属性 src
var ldh=document.getElementById('ldh');
var zxy=document.getElementById('zxy');
var img=document.querySelector('img');
zxy.onclick=function(){
img.src='images/zxy.jpg';
img.title='张学友';
}
ldh.onclick=function(){
img.src="images/ldh.jpg";
img.title='刘德华';
}
</script>
</body>
<body>
<button>按钮</button>
<input type="text" value="输入内容">
<script>
var btn=document.querySelector('button');
var input=document.querySelector('input');
btn.onclick=function(){
input.value='被点击了';
// btn.disabled=true; 也可写作:
this.disabled=true;
// this指向的是时间函数的调用者(按钮)
}
</script>
</body>
案例:点击修改元素颜色和大小
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
div{
width: 200px;
height: 200px;
background-color: aqua;
}
</style>
</head>
<body>
<div></div>
<script>
var div=document.querySelector('div');
div.onclick=function(){
this.style.backgroundColor='purple';
this.style.width='400px';
}
</script>
</body>
</html>
JS 修改 style 样式操作,产生的是行内样式,CSS 权重比较高
适合样式较多、功能复杂的情况
示例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
div{
margin: 50px;
width: 400px;
height: 200px;
background-color: pink;
}
.change{
background-color:blueviolet;
color: #fff;
font-size: 25px;
margin-top: 200px;
}
</style>
</head>
<body>
<div>文本内容</div>
<script>
var test=document.querySelector('div');
test.onclick=function(){
this.className='change';
}
</script>
</body>
</html>
在上面的例子中,如果想要保留原来的类名,可以:
<script>
var test=document.querySelector('div');
test.onclick=function(){
// this.className='change';
this.className='first change';
}
</script>
案例:被点到的按钮背景颜色变红
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
button{
margin-top: 100px;
}
</style>
</head>
<body>
<button>按钮1</button>
<button>按钮2</button>
<button>按钮3</button>
<button>按钮4</button>
<button>按钮5</button>
<script>
var btn=document.querySelectorAll('button');
for(var i=0;i<btn.length;i++){
btn[i].onclick=function(){
console.log(this.innerHTML);
for(var i=0;i<btn.length;i++){
btn[i].style.backgroundColor=''
}
this.style.backgroundColor='pink';
}
}
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="demo" index="1" class="nav"></div>
<script>
var div=document.querySelector('div');
// 获取元素属性值
// element.属性
console.log(div.id);
// element.getAttribute('属性');
console.log(div.getAttribute('id'));
// 两种方法的区别
// element.属性获取的是元素自带的内置属性值
// element.getAttribute('属性')可以获得自定义的属性
console.log(div.getAttribute('index'));
// 2. 设置元素属性值
// (1) element.属性= '值'
div.id='test';
div.className='navs';
// (2) element.setAttribute('属性', '值'); 主要针对于自定义属性
div.setAttribute('index',2);
div.setAttribute('class','footer');
div.removeAttribute('index');//移除属性
</script>
</body>
</html>
<body>
<div getTime="20" data-index="2" data-list-name="andy"></div>
<script>
var div=document.querySelector('div');
console.log(div.getAttribute('getTime'));
console.log(div.getAttribute('data-list-name'));
div.setAttribute('data-time',20);
// h5新增的获取自定义属性的方法 它只能获取data-开头的
// dataset 是一个集合里面存放了所有以data开头的自定义属性
console.log(div.dataset);
console.log(div.dataset.index);
console.log(div.dataset['index']);
// 如果自定义属性里面有多个-链接的单词,我们获取的时候采取 驼峰命名法
console.log(div.dataset.listName);
console.log(div.dataset['listName']);
</script>
</body>
操作节点
<body>
<!-- 节点的优点 -->
<div class="box">
<span class="erweima">×</span>
</div>
<script>
var box=document.querySelector('.box');
console.dir(box);
</script>
</body>
<body>
<!-- 节点的优点 -->
<div>我是div</div>
<span>我是span</span>
<ul>
<li>我是li</li>
<li>我是li</li>
<li>我是li</li>
<li>我是li</li>
</ul>
<div class="demo">
<div class="box">
<span class="erweima">×</span>
</div>
</div>
<script>
// 以前的写法
var erweima=document.querySelector('.erweima');
var box=document.querySelector('.box');
// 通过子节点获取父节点
//得到的是离元素最近的父级节点,如果找不到父节点就返回为 null
console.log(erweima.parentNode);
</script>
</body>
<body>
<!-- 节点的优点 -->
<div>我是div</div>
<span>我是span</span>
<ul>
<li>我是li</li>
<li>我是li</li>
<li>我是li</li>
<li>我是li</li>
</ul>
<ol>
<li>我是li</li>
<li>我是li</li>
<li>我是li</li>
<li>我是li</li>
</ol>
<div class="demo">
<div class="box">
<span class="erweima">×</span>
</div>
</div>
<script>
// 以前的写法
var ul=document.querySelector('ul');
var lis=ul.querySelectorAll('li');
// 获取父节点的子节点 所有的子节点 包含 元素节点 文本节点等等
console.log(ul.childNodes);
// 筛选元素节点 nodeType
console.log(ul.childNodes[0].nodeType);
console.log(ul.childNodes[1].nodeType);
for(var i=0;i<ul.childNodes.length;i++){
if(ul.childNodes[i].nodeType==1){
//判断 ul.childNodes[i] 是否是元素节点
console.log(ul.childNodes[i]);
}
}
// 获取子元素节点更简单的方法
//children 获取所有的子元素节点 也是我们实际开发常用的
console.log(ul.children);
</script>
</body>
console.log(ul.childNodes);的返回值有9个元素,是因为文本节点也会被返回。
<ol>
<li>我是li1</li>
<li>我是li2</li>
<li>我是li3</li>
<li>我是li4</li>
<li>我是li5</li>
</ol>
<script>
var ol=document.querySelector('ol');
// 1. firstChild 第一个子节点 不管是文本节点还是元素节点
console.log(ol.firstChild);//返回的是一个文本节点
console.log(ol.lastChild);//返回的是一个文本节点
// 2. firstElementChild 返回第一个子元素节点 ie9才支持
console.log(ol.firstElementChild);
console.log(ol.lastElementChild);
// 3. 实际开发的写法 既没有兼容性问题又返回第一个子元素
console.log(ol.children[0]);
console.log(ol.children[ol.children.length-1]);
</script>
<body>
<div>我是div</div>
<span>我是span</span>
<script>
var div=document.querySelector('div');
// 1.nextSibling 下一个兄弟节点 包含元素节点或者 文本节点等等
console.log(div.nextSibling);
console.log(div.previousSibling);
// 2. nextElementSibling 得到下一个兄弟元素节点
console.log(div.nextElementSibling);
console.log(div.previousElementSibling);
</script>
</body>
<ul>
<li>123</li>
</ul>
<script>
// 1. 创建节点元素节点
var li = document.createElement('li');
/* 2. 添加节点 node.appendChild(child) node 父级 child 是子级
后面追加元素 类似于数组中的push */
var ul = document.querySelector('ul');
ul.appendChild(li);
// 3. 添加节点 node.insertBefore(child, 指定元素);
var lili = document.createElement('li');
lili.innerHTML='lili';
ul.insertBefore(lili, ul.children[0]);
// 4. 我们想要页面添加一个新的元素 : 1. 创建元素 2. 添加元素
</script>
<body>
<button>删除</button>
<ul>
<li>熊大</li>
<li>熊二</li>
<li>光头强</li>
</ul>
<script>
// 1.获取元素
var ul = document.querySelector('ul');
var btn = document.querySelector('button');
// 2. 删除元素 node.removeChild(child)
// ul.removeChild(ul.children[0]);
// 3. 点击按钮依次删除里面的孩子
btn.onclick = function() {
if (ul.children.length == 0) {
this.disabled = true;
} else {
ul.removeChild(ul.children[0]);
}
}
</script>
</body>
<ul>
<li>1111</li>
<li>2</li>
<li>3</li>
</ul>
<script>
var ul = document.querySelector('ul');
// 1. node.cloneNode(); 括号为空或者里面是false 浅拷贝 只复制标签不复制里面的内容
// 2. node.cloneNode(true); 括号为true 深拷贝 复制标签复制里面的内容
var lili = ul.children[0].cloneNode(true);
ul.appendChild(lili);
</script>
-
document.write() 创建元素 如果页面文档流加载完毕, 再调用这句话会导致页面重绘,原先的页面内容会丢失
-
innerHTML,通过拼接字符串的方式效率较低,建议采用数组形式
<body>
<button>点击</button>
<p>abc</p>
<div class="inner"></div>
<div class="create"></div>
<script>
// window.onload = function() {
// document.write('<div>123</div>');
// }
// 三种创建元素方式区别
/* 1. document.write() 创建元素 如果页面文档流加载完毕,
再调用这句话会导致页面重绘,原先的页面内容会丢失 */
// var btn = document.querySelector('button');
// btn.onclick = function() {
// document.write('<div>123</div>');
// }
// 2. innerHTML 创建元素
var inner = document.querySelector('.inner');
// for (var i = 0; i <= 100; i++) {
// inner.innerHTML += '<a href="#">百度</a>'
// }通过拼接字符串的方式,速度较慢
var arr = [];
for (var i = 0; i <= 100; i++) {
arr.push('<a href="#">百度</a>');
}
inner.innerHTML = arr.join('');
// 3. document.createElement() 创建元素
var create = document.querySelector('.create');
for (var i = 0; i <= 100; i++) {
var a = document.createElement('a');
create.appendChild(a);
}
</script>
</body>
innerHTML字符串拼接效率测试
<script>
function fn() {
var d1 = +new Date();
var str = '';
for (var i = 0; i < 1000; i++) {
document.body.innerHTML += '<div style="width:100px; height:2px; border:1px solid blue;"></div>';
}
var d2 = +new Date();
console.log(d2 - d1);
}
fn();
</script>
innerHTML数组效率测试
<script>
function fn() {
var d1 = +new Date();
var array = [];
for (var i = 0; i < 1000; i++) {
array.push('<div style="width:100px; height:2px; border:1px solid blue;"></div>');
}
document.body.innerHTML = array.join('');
var d2 = +new Date();
console.log(d2 - d1);
}
fn();
</script>
createElement效率测试
<script>
function fn() {
var d1 = +new Date();
for (var i = 0; i < 1000; i++) {
var div = document.createElement('div');
div.style.width = '100px';
div.style.height = '2px';
div.style.border = '1px solid red';
document.body.appendChild(div);
}
var d2 = +new Date();
console.log(d2 - d1);
}
fn();
</script>
DOM重点核心
事件高级
注册事件
<button>传统注册事件</button>
<button>方法监听注册事件</button>
<button>ie9 attachEvent</button>
<script>
var btns = document.querySelectorAll('button');
// 1. 传统方式注册事件
btns[0].onclick = function() {
alert('hi');
}
btns[0].onclick = function() {
alert('hao a u');
}
// 2. 事件侦听注册事件 addEventListener
// (1) 里面的事件类型是字符串 必定加引号 而且不带on
// (2) 同一个元素 同一个事件可以添加多个侦听器(事件处理程序)
btns[1].addEventListener('click', function() {
alert(22);
})
btns[1].addEventListener('click', function() {
alert(33);
})
</script>
解绑事件
<div>1</div>
<div>2</div>
<div>3</div>
<script>
var divs = document.querySelectorAll('div');
divs[0].onclick = function() {
alert(11);
// 1. 传统方式删除事件
divs[0].onclick = null;
}
// 2. removeEventListener 删除事件
divs[1].addEventListener('click', fn) // 里面的fn 不需要调用加小括号
function fn() {
alert(22);
divs[1].removeEventListener('click', fn);
}
</script>
DOM事件流
如果addEventListener 第三个参数是 true 那么则处于捕获阶段
如果addEventListener 第三个参数是 false 或者 省略 那么则处于冒泡阶段
捕获阶段:点击(事件发生)son时会先执行father的事件处理函数,再执行son的事件处理函数,事件向下传播
冒泡阶段:点击(事件发生)son时会先执行son的事件处理函数,再执行father的事件处理函数,事件向上传播
<div class="father">
<div class="son">son盒子</div>
</div>
<script>
// dom 事件流 三个阶段
// 1. JS 代码中只能执行捕获或者冒泡其中的一个阶段。
// 2. onclick 和 attachEvent(ie) 只能得到冒泡阶段。
// 3. 捕获阶段 如果addEventListener 第三个参数是 true 那么则处于捕获阶段
// document -> html -> body -> father -> son
// var son = document.querySelector('.son');
// son.addEventListener('click', function() {
// alert('son');
// }, true);
// var father = document.querySelector('.father');
// father.addEventListener('click', function() {
// alert('father');
// }, true);
// 4. 冒泡阶段 如果addEventListener 第三个参数是 false 或者 省略 那么则处于冒泡阶段
//son -> father ->body -> html -> document
var son = document.querySelector('.son');
son.addEventListener('click', function() {
alert('son');
}, false);
var father = document.querySelector('.father');
father.addEventListener('click', function() {
alert('father');
}, false);
document.addEventListener('click', function() {
alert('document');
})
</script>
事件对象
<div>123</div>
<script>
// 事件对象
var div = document.querySelector('div');
div.onclick = function(e) {//兼容性处理
console.log(e);
console.log(window.event);
e = e || window.event;
console.log(e);
}
// div.addEventListener('click', function(e) {
// console.log(e);
// })
// 1. event 就是一个事件对象 写到我们侦听函数的 小括号里面 当形参来看
// 2. 事件对象只有有了事件才会存在,它是系统给我们自动创建的,不需要我们传递参数
// 3. 事件对象 是 我们事件的一系列相关数据的集合 跟事件相关的 比如鼠标点击里面就包含了鼠标的相关信息,鼠标坐标啊,如果是键盘事件里面就包含的键盘事件的信息 比如 判断用户按下了那个键
// 4. 这个事件对象我们可以自己命名 比如 event 、 evt、 e
// 5. 事件对象也有兼容性问题 ie678 通过 window.event 兼容性的写法 e = e || window.event;
</script>
e.target 返回的是触发事件的对象(元素)
this 返回的是绑定事件的对象(元素)
区别 : e.target 点击了那个元素,就返回那个元素
this 那个元素绑定了这个点击事件,那么就返回谁
<div>123</div>
<ul>
<li>abc</li>
<li>abc</li>
<li>abc</li>
</ul>
<script>
/* 1. e.target 返回的是触发事件的对象(元素)
this 返回的是绑定事件的对象(元素)
区别 : e.target 点击了那个元素,就返回那个元素
this 那个元素绑定了这个点击事件,那么就返回谁 */
var div = document.querySelector('div');
div.addEventListener('click', function(e) {
console.log(e.target);
console.log(this);
})
var ul = document.querySelector('ul');
ul.addEventListener('click', function(e) {
// 我们给ul 绑定了事件 那么this 就指向ul
console.log(this);
console.log(e.currentTarget);
// e.target 指向我们点击的那个对象 谁触发了这个事件
// 触发事件的是li,因为冒泡,所以事件被ul捕获并执行事件处理函数
// 我们点击的是li e.target 指向的就是li
console.log(e.target);
})
// 了解兼容性
// div.onclick = function(e) {
// e = e || window.event;
// var target = e.target || e.srcElement;
// console.log(target);
// }
// 2. 了解 跟 this 有个非常相似的属性 currentTarget ie678不认识
</script>
e.type:返回事件类型
阻止默认行为(事件) 如:让链接不跳转 或者让提交按钮不提交
普通浏览器: e.preventDefault(); 方法
低版本浏览器: ie678 returnValue 属性
我们可以利用 return false 也能阻止默认行为 没有兼容性问题 ,特点: return 后面的代码不执行了, 而且只限于传统的注册方式
<div>123</div>
<a href="http://www.baidu.com">百度</a>
<form action="http://www.baidu.com">
<input type="submit" value="提交" name="sub">
</form>
<script>
// 常见事件对象的属性和方法
// 1. 返回事件类型
var div = document.querySelector('div');
div.addEventListener('click', fn);
div.addEventListener('mouseover', fn);
div.addEventListener('mouseout', fn);
function fn(e) {
console.log(e.type);
}
// 2. 阻止默认行为(事件) 让链接不跳转 或者让提交按钮不提交
var a = document.querySelector('a');
a.addEventListener('click', function(e) {
e.preventDefault(); // dom 标准写法
})
// 3. 传统的注册方式
a.onclick = function(e) {
// 普通浏览器 e.preventDefault(); 方法
// e.preventDefault();
// 低版本浏览器 ie678 returnValue 属性
// e.returnValue;
// 我们可以利用return false 也能阻止默认行为 没有兼容性问题
// 特点: return 后面的代码不执行了, 而且只限于传统的注册方式
return false;
alert(11);
}
</script>
阻止事件冒泡
<div class="father">
<div class="son">son儿子</div>
</div>
<script>
// 常见事件对象的属性和方法
// 阻止冒泡 dom 推荐的标准 stopPropagation()
var son = document.querySelector('.son');
son.addEventListener('click', function(e) {
alert('son');
e.stopPropagation(); // stop 停止 Propagation 传播
e.cancelBubble = true; // 非标准 cancel 取消 bubble 泡泡
}, false);
var father = document.querySelector('.father');
father.addEventListener('click', function() {
alert('father');
}, false);
document.addEventListener('click', function() {
alert('document');
})
</script>
事件委托(代理、委派)
<ul>
<li>知否知否,点我应有弹框在手!</li>
<li>知否知否,点我应有弹框在手!</li>
<li>知否知否,点我应有弹框在手!</li>
<li>知否知否,点我应有弹框在手!</li>
<li>知否知否,点我应有弹框在手!</li>
</ul>
<script>
// 事件委托的核心原理:给父节点添加侦听器, 利用事件冒泡影响每一个子节点
var ul = document.querySelector('ul');
ul.addEventListener('click', function(e) {
// alert('知否知否,点我应有弹框在手!');
// e.target 这个可以得到我们点击的对象
e.target.style.backgroundColor = 'pink';
})
</script>
7. 常用的鼠标事件
<body>
我是一段不愿意分享的文字
<script>
// 1. contextmenu 我们可以禁用右键菜单
document.addEventListener('contextmenu', function(e) {
e.preventDefault();
})
// 2. 禁止选中文字 selectstart
document.addEventListener('selectstart', function(e) {
e.preventDefault();
})
</script>
</body>
- client 鼠标在可视区的x和y坐标,页面滚动条拖动后不会影响返回的坐标
- page 鼠标在页面文档的x和y坐标
- screen 鼠标在电脑屏幕的x和y坐标
<style>
body {
height: 3000px;
}
</style>
</head>
<body>
<script>
// 鼠标事件对象 MouseEvent
document.addEventListener('click', function(e) {
// 1. client 鼠标在可视区的x和y坐标,不管页面滚动条是否拖动
console.log(e.clientX);
console.log(e.clientY);
console.log('---------------------');
// 2. page 鼠标在页面文档的x和y坐标
console.log(e.pageX);
console.log(e.pageY);
console.log('---------------------');
// 3. screen 鼠标在电脑屏幕的x和y坐标
console.log(e.screenX);
console.log(e.screenY);
})
</script>
</body>
滚动前后点击屏幕同一位置
案例:
跟随鼠标移动的天使
案例分析
① 鼠标不断的移动,使用鼠标移动事件: mousemove
② 在页面中移动,给document注册事件
③ 图片要移动距离,而且不占位置,我们使用绝对定位即可
④ 核心原理: 每次鼠标移动,我们都会获得最新的鼠标坐标, 把这个x和y坐标做为图片的
top和left 值就可以移动图片
<style>
img {
position: absolute;
top: 2px;
}
</style>
</head>
<body>
<img src="images/angel.gif" alt="">
<script>
var pic = document.querySelector('img');
document.addEventListener('mousemove', function(e) {
// 1. mousemove只要我们鼠标移动1px 就会触发这个事件
// console.log(1);
// 2.核心原理: 每次鼠标移动,我们都会获得最新的鼠标坐标, 把这个x和y坐标做为图片的top和left 值就可以移动图片
var x = e.pageX;
var y = e.pageY;
console.log('x坐标是' + x, 'y坐标是' + y);
//3 . 千万不要忘记给left 和top 添加px 单位
pic.style.left = x - 50 + 'px';
pic.style.top = y - 40 + 'px';
});
</script>
</body>
键盘事件
<script>
// 常用的键盘事件
//1. keyup 按键弹起的时候触发
// document.onkeyup = function() {
// console.log('我弹起了');
// }
document.addEventListener('keyup', function() {
console.log('我弹起了');
})
//3. keypress 按键按下的时候触发 不能识别功能键 比如 ctrl shift 左右箭头啊
document.addEventListener('keypress', function() {
console.log('我按下了press');
})
//2. keydown 按键按下的时候触发 能识别功能键 比如 ctrl shift 左右箭头啊
document.addEventListener('keydown', function() {
console.log('我按下了down');
})
// 4. 三个事件的执行顺序 keydown -- keypress -- keyup
</script>
键盘事件对象中的keyCode属性可以得到相应键的ASCII码值
- 我们的keyup 和keydown事件不区分字母大小写 a 和 A 得到的都是65
- 我们的keypress 事件 区分字母大小写 a 97 和 A 得到的是65
<script>
// 键盘事件对象中的keyCode属性可以得到相应键的ASCII码值
// 1. 我们的keyup 和keydown事件不区分字母大小写 a 和 A 得到的都是65
// 2. 我们的keypress 事件 区分字母大小写 a 97 和 A 得到的是65
document.addEventListener('keyup',function(e){
console.log(e);
console.log('up:' + e.keyCode);
})
document.addEventListener('keypress',function(e){
console.log('press:' + e.keyCode);
})
</script>