Eloquent JavaScript #12# Handling Events
索引
Notes
1、onclick
<button onclick="copyText()">Copy Text</button>
2、removeEventListener
<button>Act-once button</button>
<script>
let button = document.querySelector("button");
function once() {
console.log("Done.");
button.removeEventListener("click", once);
}
button.addEventListener("click", once);
</script>
3、Event objects
<button>Click me any way you want</button>
<script>
let button = document.querySelector("button");
button.addEventListener("mousedown", event => {
if (event.button == 0) {
console.log("Left button");
} else if (event.button == 1) {
console.log("Middle button");
} else if (event.button == 2) {
console.log("Right button");
}
});
</script>
4、stopPropagation
<p>A paragraph with a <button>button</button>.</p>
<script>
let para = document.querySelector("p");
let button = document.querySelector("button");
para.addEventListener("mousedown", () => {
console.log("Handler for paragraph.");
});
// 左键传播,右键不传播。
button.addEventListener("mousedown", event => {
console.log("Handler for button.");
if(event.button == 2) event.stopPropagation();
});
</script>
5、event.target
<button>A</button>
<button>B</button>
<button>C</button>
<script>
document.body.addEventListener("click", event => {
if(event.target.nodeName == "BUTTON") {
console.log("Clicked", event.target.textContent);
}
});
</script>
6、Default actions
<a href="https://developer.mozilla.org/">MDN</a>
<script>
let link = document.querySelector("a");
// 事件处理器在默认行为发生之前被调用
link.addEventListener("click", event => {
console.log("Nope.");
event.preventDefault(); // 例如ctrl+w是无法被prevent的
});
</script>
7、Key events
<p>This page turns violet when you hold the V key.</p>
<script>
window.addEventListener("keydown", event => {
if(event.key == "v") {
document.body.style.background = "violet";
console.log("repeat"); // 只要按住就会不断触发,而不是仅触发一次。
}
});
window.addEventListener("keyup", event => {
if(event.key == "v") {
document.body.style.background = "";
}
});
</script>
组合按键:
<p>Press Control-Space to continue.</p>
<script>
window.addEventListener("keydown", event => {
if(event.key == " " && event.ctrlKey) {
console.log("Continuing!");
}
});
</script>
8、Mouse motion
一个可以拖动的进度条:
<p>Drag the bar to change its width:</p>
<div style="background: orange; width: 60px; height: 20px">
</div>
<script>
let lastX; // Tracks the last observed mouse X position
let bar = document.querySelector("div");
bar.addEventListener("mousedown", event => {
if(event.button == 0) { // 鼠标左键
lastX = event.clientX;
window.addEventListener("mousemove", moved);
event.preventDefault(); // Prevent selection
}
}); function moved(event) {
if(event.buttons == 0) {
// MouseEvent.buttons可指示任意鼠标事件中鼠标的按键情况
// 仅按下左键1 仅按下右键2 仅按下滚轮4 ,同时按下多个则取和
// 这个示例的现象在于,只有在进度条上按下左键才可以开启事件
// 之后快速换鼠标右键(或者n个键)拖动也可以。
window.removeEventListener("mousemove", moved);
} else {
let dist = event.clientX - lastX;
let newWidth = Math.max(10, bar.offsetWidth + dist); // 10是最小宽度
bar.style.width = newWidth + "px";
lastX = event.clientX;
}
}
</script>
9、Touch events
触屏和鼠标点击是不同的,但是触屏仍然默认会触发一些鼠标事件。
<!DOCTYPE html>
<html> <head>
<meta charset="UTF-8">
<title></title>
<style>
dot {
position: absolute;
display: block;
border: 2px solid red;
border-radius: 50px;
height: 100px;
width: 100px;
}
</style>
</head> <body>
<p>Touch this page</p>
<script>
function update(event) {
for(let dot; dot = document.querySelector("dot");) {
dot.remove();
}
for(let i = 0; i < event.touches.length; i++) {
let {
pageX,
pageY
} = event.touches[i];
let dot = document.createElement("dot");
dot.style.left = (pageX - 50) + "px";
dot.style.top = (pageY - 50) + "px";
document.body.appendChild(dot);
}
}
window.addEventListener("touchstart", update);
window.addEventListener("touchmove", update);
window.addEventListener("touchend", update);
</script>
</body> </html>
10、Scroll events
监控滚动条的状况:
<!DOCTYPE html>
<html> <head>
<meta charset="UTF-8">
<title></title>
<style>
#progress {
border-bottom: 2px solid blue;
width: 0;
position: fixed;
top: 0;
left: 0;
}
</style>
</head> <body>
<div id="progress"></div>
<script>
// Create some content
document.body.appendChild(document.createTextNode(
"supercalifragilisticexpialidocious ".repeat(1000))); let bar = document.querySelector("#progress");
window.addEventListener("scroll", () => {
let max = document.body.scrollHeight - innerHeight;
bar.style.width = `${(pageYOffset / max) * 100}%`;
});
</script>
</body> </html>
采用preventDefault不会阻止默认事件(滚动)发生,因为滚动是在调用事件处理器之前执行的。
11、Focus events
注意Focus事件是不会传播的。
<p>Name: <input type="text" data-help="Your full name"></p>
<p>Age: <input type="text" data-help="Your age in years"></p>
<p id="help"></p> <script>
let help = document.querySelector("#help");
let fields = document.querySelectorAll("input");
for (let field of Array.from(fields)) {
field.addEventListener("focus", event => {
let text = event.target.getAttribute("data-help");
help.textContent = text;
});
field.addEventListener("blur", event => {
help.textContent = "";
});
}
</script>
12、Load event
Load事件同样是不传播的。
beforeunload - Event reference | MDN
13、Events and the event loop
事件处理器在事件发生的时候就已经被“安排”了,但是也必须等到别的脚本执行完才有机会执行。在有很多或者很耗时的脚本时,页面就有可能被“冻”住,为了解决这个问题,应该把繁重、长时间的计算放在一个单独的线程里。副脚本不会和主脚本共享作用域,只有可以表达为JSON的数据才可以在两者之间传递。
js/squareworker.js↓
addEventListener("message", event => {
postMessage(event.data * event.data);
});
index.html↓
<!DOCTYPE html>
<html> <head>
<meta charset="UTF-8">
<title></title>
</head> <body>
<script>
let squareWorker = new Worker("js/squareworker.js");
squareWorker.addEventListener("message", event => {
console.log("The worker responded:", event.data);
});
squareWorker.postMessage(10);
squareWorker.postMessage(24);
</script>
</body> </html>
14、Timers
取消setTimeout回调:
<!DOCTYPE html>
<html> <head>
<meta charset="UTF-8">
<title></title>
</head> <body>
<script>
let bombTimer = setTimeout(() => {
console.log("BOOM!");
}, 500); if(Math.random() < 0.5) { // 50% chance
console.log("Defused.");
clearTimeout(bombTimer);
}
</script>
</body> </html>
取消setInterval回调:
<!DOCTYPE html>
<html> <head>
<meta charset="UTF-8">
<title></title>
</head> <body>
<script>
let ticks = 0;
let clock = setInterval(() => {
console.log("tick", ticks++);
if(ticks == 10) {
clearInterval(clock);
console.log("stop.");
}
}, 200);
</script>
</body> </html>
15、Debouncing
某些类型的事件有可能会被连续触发n次(例如“鼠标移动”和“滚动”事件)。处理此类事件时,必须注意不要做太费时间的操作,否则处理程序会占用很多时间,以至于与文档的交互开始变得缓慢。如果你确实需要在这样的处理程序中做一些非常重要的事情,你可以使用setTimeout来降低触发长时操作的频率。这通常被称为Debouncing(去抖动)。有几种略有不同的实现方式。
例子一,持续输入0.5秒输出一个Typed!:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<textarea>Type something here...</textarea>
<script>
let textarea = document.querySelector("textarea");
let timeout;
textarea.addEventListener("input", () => {
clearTimeout(timeout);
timeout = setTimeout(() => console.log("Typed!"), 500);
});
</script>
</body>
</html>
例子二,间隔250ms响应一次鼠标移动:
<!DOCTYPE html>
<html> <head>
<meta charset="UTF-8">
<title></title>
</head> <body>
<script>
let scheduled = null;
window.addEventListener("mousemove", event => {
if(!scheduled) {
setTimeout(() => {
document.body.textContent =
`Mouse at ${scheduled.pageX}, ${scheduled.pageY}`;
scheduled = null;
}, 250);
}
scheduled = event;
});
</script>
</body> </html>
Exercise
① Balloon
<!DOCTYPE html>
<html> <head>
<meta charset="UTF-8">
<title></title>
</head> <body>
<p>Eloquent JavaScript #12# Handling Events的更多相关文章
- Javascript Madness: Mouse Events
http://unixpapa.com/js/mouse.html Javascript Madness: Mouse Events Jan WolterAug 12, 2011 Note: I ha ...
- Eloquent JavaScript #13# HTTP and Forms
索引 Notes fetch form focus Disabled fields form’s elements property 阻止提交 快速插入单词 实时统计字数 监听checkbox和rad ...
- (4)事件处理——(1)事件处理(Handling Events)
JavaScript has several built-in ways of reacting to user interaction and other events. To make a pag ...
- Eloquent JavaScript #04# Objects and Arrays
要点索引: JSON More ... 练习 1.补:js字符串的表达方式有三种: "" 和 '' 没什么区别,唯一区别在于 "" 中写 "要转义字符 ...
- Handling events in an MVVM WPF application
Posted: June 30, 2013 | Filed under: MVVM, WPF, XAML |1 Comment In a WPF application that uses the ...
- [transferred] javascript exception handling.
my error handling clause: window.onerror = function (errorMessage, scriptURI, lineNumber, columnNumb ...
- 从零开始学习前端JAVASCRIPT — 12、JavaScript面向对象编程
一.构造函数的使用 <!DOCTYPE html> <html lang="en"> <head> <meta charset=" ...
- Eloquent JavaScript #11# The Document Object Model
索引 Notes js与html DOM 在DOM树中移动 在DOM中寻找元素 改变Document 创建节点 html元素属性 布局 style CSS选择器 动画 Exercises Build ...
- Eloquent JavaScript #10# Modules
索引 Notes 背景问题 模块Modules 软件包Packages 简易模块 Evaluating data as code CommonJS modules ECMAScript modules ...
随机推荐
- mybatis {arg0} 与 {0}
解决方案: MyBatis的XML的配置文件中声明设置属性的useActualParamName参数值为假 <setting name="useActualParamName" ...
- 2019.03.24 Ajax
也还是会用到jquery中的Ajax请i求 所以第一还是引入jQuery包 可以去网上搜腾讯网静态资源库 然后引入包 Ajax还是异步处理 处理堵塞问题 import time 就可以了 ...
- jenkins 新增用户和修改用户名密码
在某些条件下,jenkins是不允许注册用户的,这是,你可以采用如下的方式来新增用户,对于老的用户,忘记密码了,使用如下方式来重置密码. 1.系统管理-->管理用户 ----> 新建用户 ...
- c# 利用MailKit.IMap 收取163邮件
最近我要做一个爬虫.这个爬虫需要如下几个步骤: 1 填写注册内容(需要邮箱注册) 2 过拖拽验证码(geetest) 3 注册成功会给邮箱发一封确认邮箱 4 点击确认邮箱中的链接 完成注册 我这里就采 ...
- python timeit
//有时候,我们想知道一个函数的计算耗时,那么,你可以用timeit //test.py 1 import timeit 2 3 def func(): 4 s = 0 5 ...
- Docker ssh server
这个话题真让我气愤啊,在家里的mac上我已经全部摆平了,结果在公司的Linux上就给堵住了 原因不祥,但最后在错误提示里,有个移除(remove)信息,我照做了,就没问题了,全通了 大概是linux里 ...
- .Net拾忆:从List去除重复-拾忆集合
方法1: private static List<int> DistinctList(List<int> list) {//去除重复 HashSet<int> ha ...
- (已解决)Xcode 运行cocos2dx弹出内部错误对话框(Internal Error)
cocos2dx未捕获的异常升高.选择“继续”继续运行在一个不一致的状态.选择“崩溃”停止应用和崩溃报告一个错误文件. 莫名其妙,代码没有报错,运行时却弹出(内部错误)对话框出来: 再看看崩溃的底层代 ...
- django项目mysql中文编码问题
在做django+mysql项目的时候,遇到中文报错问题. 问题分析:是由于mysql数据库,字符集的问题 在cmd命令行模式进入mysql mysql -uroot -p以root身份进入mysql ...
- Linux之HugePages快速配置
关于Linux系统的HugePages与Oracle数据库优化,可以参考熊爷之前的文章,相关概念介绍的非常清晰: Linux大内存页Oracle数据库优化 本文旨在Linux系统上快速配置HugePa ...