文章目录
一、常用键盘事件:
1. 键盘事件:
键盘事件 | 触发条件 |
---|---|
onkeyup | 某个按键被松开时触发 |
onkeydown | 某个按年被按下时触发 |
onkeypress | 某个按键被按下时触发(不识别功能按键, 如:ctrl, shift,箭头等) |
注意:
- 如果使用addEventListener不需要加on;
- onkeypress不识别功能按键, 如:ctrl, shift,箭头等;
- 三个事件的执行顺序: keydown --> keypress --> keyup
<script>
// 常用的键盘事件
//1. keyup 按键弹起的时候触发
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>
2. 键盘事件对象:
键盘事件对象属性 | 说明 |
---|---|
keyCode | 返回该键的ASCII的值 |
注意:
- onkeydown和onkeyup不区分字幕大小写, onkeypress区分字母大小写;
- 在实际开发中, 更多的使用keydown和keyup, 它能识别所有的键(包括功能键);
- keypress不识别功能键, 但是keyCode属性能区分大小写, 返回不同的ASCII值;
2.1 使用keyCode属性判断用户按下哪个键:
<script>
// 键盘事件对象中的keyCode属性可以得到相应键的ASCII码值
document.addEventListener('keyup', function(e) {
console.log('up:' + e.keyCode);
// 可以利用keycode返回的ASCII码值来判断用户按下了那个键
if (e.keyCode === 65) {
alert('您按下的a键');
} else {
alert('您没有按下a键')
}
})
document.addEventListener('keypress', function(e) {
// console.log(e);
console.log('press:' + e.keyCode);
})
</script>
3. 案例: 模拟京东按键输入内容:
当按下s键, 光标就定位到搜索框(文本框获得焦点)
3.1 案例分析:
- 核心思路: 检测用户是否按下s键, 如果按下s键, 就把光标定位到搜索框里;
- 使用键盘事件对象里面的keyCode判断用户按下的是否是s键;
- 搜索框获得焦点,: 使用js里面的focus()方法;
3.2 实现:
<head>
<title>京东按键</title>
<script>
window.onload = function() {
var search = document.querySelector('input');
document.addEventListener('keyup', function(e) {
// 判断keyCode值
if(e.keyCode === 83) {
search.focus();
}
})
}
</script>
</head>
<body>
<input type="text">
</body>
4. 案例: 模拟京东快递单号查询
要求: 当在文本框输入内容是,文本框上边自动显示大字号的内容;
4.1 案例分析:
- 快单号输入内容时, 上面的大字号字体盒子(con)显示这里面的文字;
- 同时把快递单号里面的值(value)获取过来赋值给coon盒子(innerText)作为内容;
- 如果快递单号里面内容为空, 则隐藏大号字体盒子(con)盒子;
- 注意: keydown和keypress在文本里面的特点: 他们两个事件触发的时间, 文字还没有落入文本框中;
- keyup事件触发的时候, 文字已经落入文本框里面了;
- 当失去焦点, 就隐藏这个con盒子;
- 当获得焦点, 并且文本框内容不为空, 就显示这个con盒子;
4.2 实现:
<head>
<title>京东单号</title>
<style>
.con {
font-size: 26px;
}
</style>
<script>
window.onload = function() {
var con = document.querySelector('.con');
var jd_input = document.querySelector('.jd');
jd_input.addEventListener('keyup', function(e){
if(this.value == ''){
// 为空, 隐藏放大盒子
con.style.display = 'none';
} else {
// 不为空, 显示放大盒子
con.style.display = 'block';
con.innerHTML = this.value;
}
})
// 给输入框注册失去焦点事件, 隐藏放大盒子
jd_input.addEventListener('blur', function(e) {
con.style.display = 'none';
})
// 给输入框注册获得焦点事件
jd_input.addEventListener('focus', function(e) {
// 判断输入框内容是否为空
if(this.value !== '') {
con.style.display = 'block';
}
})
}
</script>
</head>
<body>
<div class="search">
<div class="con">123</div>
<input type="text" name="" id=""placeholder="请输入您的快递单号" class="jd">
</div>
</body>
二、BOM:
1. 什么是BOM:
- BOM(Browser Object Model)即浏览器对象模型,它提供了独立于内容而与浏览器窗口进行交互的对象,其核心对象是 window;
- BOM 由一系列相关的对象构成,并且每个对象都提供了很多方法与属性;
- BOM 缺乏标准,JavaScript 语法的标准化组织是 ECMA,DOM 的标准化组织是 W3C,BOM 最初是Netscape 浏览器标准的一部分;
2. BOM的构成
BOM 比 DOM 更大, 它包含 DOM.
3. 顶级对象window
window对象是浏览器的顶级对象, 它具有双重角色:
- 它是js访问浏览器窗口的一个接口;
- 它是一个全局对象. 定义在全局作用域中的变量, 函数都会变成window对象的属性和方法;
在调用的时候可以省略window, 如:alert(), prompt()等.
注意:
window下的一个特殊属性window.name
4. window对象的常见事件:
4.1 页面(窗口)加载事件(2种):
第一种:
window.onload = function() {}
或者:
window.addEventListener("load", function() {});
window.onload 是窗口 (页面)加载事件, 当文档内容完全加载完成会触发该事件(包括图像、脚本文件、CSS 文件等), 就调用的处理函数
注意:
- 有了window.onload就可以把JS代码写在只能写一次, 如果有多次, 会最后一个window.onlad为准;
- 如果使用addEventListener则没有限制;
第二种:
document.addEventListener('DOMContentLoaded', function() { })
- DOMContentLoaded 事件触发时,仅当DOM加载完成,不包括样式表,图片,flash等等;
- IE9以上才支持!!!
- 如果页面的图片很多的话, 从用户访问到onload触发可能需要较长的时间, 交互效果就不能实现,必然影响用户的体验,此时用 DOMContentLoaded 事件比较合适;
<head>
<title>BOM加载</title>
<script>
// 后加载
window.addEventListener('load', function() {
var btn = document.querySelector('button');
btn.addEventListener('click', function() {
alert('点击我');
})
})
window.addEventListener('load', function() {
alert(22);
})
document.addEventListener('DOMContentLoaded', function() {
alert(33);
})
</script>
</head>
<body>
<button>惦记我</button>
</body>
4.2 调整窗口大小事件:
window.onresize = function()
window.addEventListener('resize', function() {});
window.onresize 是调整窗口大小加载事件, 当触发时就调用的处理函数。
**注意: **
- 只要窗口大小发生像素变化,就会触发这个事件。
- 利用这个事件完成响应式布局; window.innerWidth 当前屏幕的宽度;
<head>
<title>响应布局</title>
<style>
div {
width: 300px;
height: 300px;
background-color: pink;
}
</style>
<script>
window.onload = function() {
var div = document.querySelector('div');
window.addEventListener('resize', function() {
console.log("当前宽度:" + window.innerWidth + ", 高度:" + window.innerHeight);
if(window.innerWidth <= 800) {
div.style.display = 'none';
} else {
div.style.display = 'block';
}
})
}
</script>
</head>
<body>
<div></div>
</body>
5. 定时器(两种):
window 对象给提供了 2 个非常好用的方法-定时器。
- setTimeout()
- setInterval()
5.1 setTimeout() 炸弹定时器
开启定时器
window.setTimeout(调用函数 [, 延迟的毫秒数])
setTimeout()这个调用函数称之为回调函数callback
注意:
- window可以省略;
- 这个调用函数可以直接写函数, 函数名或者**采取字符串’函数名()’**三种形式; 第三种不推荐;
- 延迟的毫秒数省略默认是0, 如果写,必须写毫秒;
- 因为定时器可能很多, 所以经常会给定时器赋值一个标识;
普通函数是按照代码顺序直接调用;
简单理解: 回调,就是回头调用的意思; 上一件事干完,再回头再调用这个函数;
例如: 定时器中的调用函数,事件处理函数,也是回调函数;
element.onclick = function(){} 或者 element.addEventListener(“click”, fn) ; 里面的 函数也是回调函数;
<head>
<title>定时器</title>
<script>
// 回调函数是一个匿名函数
setTimeout(function() {
console.log('时间到...')
}, 2000)
function callback() {
console.log('callback...')
}
var timer1 = setTimeout(callback, 4000);
var timer2 = setTimeout(callback, 5000);
</script>
</head>
<body>
</body>
5.1.1 案例: 5秒钟后关闭广告
案例分析:
- 核心思路: 5秒之后, 就把广告隐藏起来;
- 用定时器setTimeout
实现:
<head>
<title>5秒关闭广告</title>
<script>
window.onload = function() {
var ad = document.querySelector('.ad');
// 开启定时器
setTimeout(function() {
ad.style.display = 'none';
}, 5000)
}
</script>
</head>
<body>
<img src="./images/AD.png" class = 'ad' alt="">
</body>
5.1.2 停止定时器:
window.clearTimeout(timeoutID)
window.clearTimeout()方法取消了先前通过调用setTimeout()建立的定时器
注意:
- window可以省略;
- 里面的参数就是定时器的标志符;
<head>
<title>Document</title>
</head>
<body>
<button>点击停止定时器</button>
<script>
var btn = document.querySelector('button');
// 开启定时器
var timer = setTimeout(function() {
console.log('爆炸了');
}, 5000);
// 给按钮注册单击事件
btn.addEventListener('click', function() {
// 停止定时器
clearTimeout(timer);
})
</script>
</body>
5.2 setInterval() 闹钟定时器:
开启定时器
window.setInterval(回调函数 [, 间隔毫秒数])
window.setInterval()方法重复调用一个函数, 每隔一段时间, 就去调用一个回调函数
注意:
- window可以省略;
- 这个调用函数可以直接写函数, 或者写函数名, 或者采取字符串’函数名()’ 三种形式;
- 间隔的毫秒数省略默认是0, 如果写, 必须是毫秒, 表示每隔多少毫秒就自动调用这个函数;
- 因为定时器可能有很多, 所以经常给定时器赋值一个标识符;
- 第一次执行也就是间隔毫秒数之后执行, 之后每隔毫秒数执行一次;
<head>
<title>循环定时器</title>
<script>
// 1. setInterval
setInterval(function() {
console.log('继续输出');
}, 1000);
</script>
</head>
5.2.2 案例:倒计时
案例分析
- 这个倒计时是不断变化的, 因此需要定时器来自动变化(setInterval);
- 三个黑色盒子里面分别存放时分秒;
- 三个黑色盒子利用innerHTML放入计算的小时分钟秒数;
- 第一次执行也是间隔毫秒数, 因此刚刷新的页面会有空白;
- 最好采用封装函数的方式, 这样可以先调用一次这个函数, 防止刚开始刷洗页面的空白页面;
实现:
<head>
<title>京东秒杀</title>
<script>
window.onload = function() {
var hour = document.querySelector('.hour')
var minute = document.querySelector('.minute')
var second = document.querySelector('.second')
var inputTime = +new Date('2020-5-1 18:00:00'); // 返回的是用户输入时间总的毫秒数
// 定义函数
function countDown() {
var nowTime = +new Date(); // 返回的是当前时间总的毫秒数
var times = (inputTime - nowTime) / 1000; // times是剩余时间总的秒数
var h = parseInt(times / 60 / 60); //时
h = h < 10 ? '0' + h : h;
hour.innerHTML = h; // 把剩余的小时给 小时黑色盒子
var m = parseInt(times / 60 % 60); // 分
m = m < 10 ? '0' + m : m;
minute.innerHTML = m;
var s = parseInt(times % 60); // 当前的秒
s = s < 10 ? '0' + s : s;
second.innerHTML = s;
}
// 防止页面刷新有空白
countDown();
// 开启定时器
setInterval(countDown, 1000);
}
</script>
</head>
<body>
<div>
<p>距离2020-05-02 18:00:00 还有</p>
<span class="hour">1</span>:
<span class="minute">2</span>:
<span class="second">3</span>
</div>
</body>
5.2.2 停止定时器:
window.clearInterval(IntervalID)
clearInterval()方法取消了先前通过调用setInterval()建立的定时器;
注意:
- window可以省略;
- 里面的参数就是定时器的标志符;
5.2.3 案例:发送短信倒计时:
点击按钮后,该按钮60秒之内不能再次点击,防止重复发送短信
案例分析:
- 按钮点击之后, 会禁用disable为true;
- 同事按钮里面的内容会变化, 注意button里面的内容通过innerHTML修改;
- 里面秒数是会变化的, 因此需要用到定时器;
- 定义一个变量, 在定时器里面, 不断递减;
- 如果变量为0, 说明时间到了, 需要停止定时器, 并且复原按钮初始状态;
实现:
<head>
<title>短信倒计时</title>
<script>
window.onload = function() {
var tel = document.querySelector('.tel');
var btn = document.querySelector('button')
var time = 180; // 倒计时的秒数
// 注册点击事件
btn.addEventListener('click', function() {
// 禁用按钮
this.disabled = true;
//开启定时器
var timer = setInterval(function() {
if(time == 0){
// 清除定时器
clearInterval(timer);
this.disabled = false;
this.innerHTML = "发送短信";
} else {
btn.innerHTML = "还有"+ time + '秒';
time --;
}
}, 1000)
})
}
</script>
</head>
<body>
手机号: <input type="tel" name="" id="" class="tel">
<button>发送短信</button>
</body>
6. this指向问题:
this的指向在函数定义的时候是确定不了的,只有函数执行的时候才能确定this到底指向谁,一般情况下this的最终指向的是那个调用它的对象.
- 全局作用域或者普通函数中this指向全局对象window(注意定时器里面的this指向window)
- 方法调用中谁调用this指向谁;
- 构造函数中this指向构造函数的实例;
<button>点击</button>
<script>
// this 指向问题 一般情况下this的最终指向的是那个调用它的对象
// 1. 全局作用域或者普通函数中this指向全局对象window( 注意定时器里面的this指向window)
console.log(this);
function fn() {
console.log(this);
}
window.fn();
window.setTimeout(function() {
console.log(this);
}, 1000);
// 2. 方法调用中谁调用this指向谁
var o = {
sayHi: function() {
console.log(this); // this指向的是 o 这个对象
}
}
o.sayHi();
var btn = document.querySelector('button');
btn.addEventListener('click', function() {
console.log(this); // 事件处理函数中的this指向的是btn这个按钮对象
})
// 3. 构造函数中this指向构造函数的实例
function Fun() {
console.log(this); // this 指向的是fun 实例对象
}
var fun = new Fun();
</script>
7. location对象:
7.1 什么是location对象:
window对象给提供了一个location属性用于获取或设置窗体的url, 并且可以用于解析url. 因为设个属性返回的是一个对象, 所以这个属性也被称之为location对象
7.2 URL:
**统一资源定位符(Uniform Resource Locator, URL)**是互联网上标准资源的地址. 互联网上每个文件都有唯一的一个URL, 它包含的信息支出文件的位置以及浏览器应该如何处理它
url一般的语法格式为:
protool:/host[:port]/path/[?query] # fragment
http://www.baidu.com/index?name=andy&age=18#link
组成 | 说明 |
---|---|
protool | 通讯协议(常用的http, https,ftp,maito等) |
host | 主机名(域名, ip)www.baidu.com |
port | 端口号(可选),省略时使用协议默认端口号, 如;http: 80; https:443 |
path | 路径, 由零或多个’/'符号隔开的字符串, 一般表示主机上的一个目录或文件地址 |
query | 参数, 以键值对的形式, 通过&符号链接 |
fragment | 片段 #后面内容, 常见于链接、锚点 |
7.3 location对象属性:
location对象属性 | 返回值 |
---|---|
location.href | 获取或者设置页面的url |
location.host | 返回主机名(域名) |
location.port | 返回端口号, 如果没有写, 返回空字符串 |
location.pathname | 返回路径 |
location.search | 返回参数 |
location.hash | 返回片段 #内容 |
7.4 案例: 5s后自动跳转页面
案例分析:
- 利用定时器做倒计时效果;
- 时间到了, 就跳转页面, 使用location.href
实现:
<head>
<title>跳转页面</title>
<script>
window.onload = function() {
var btn = document.querySelector('button');
var div = document.querySelector('div');
var time = 5; // 5秒
// 注册事件
btn.addEventListener('click', function() {
this.disabled = true;
setInterval(function() {
if(time == 0) {
location.href = 'http://www.baidu.com'
} else {
div.innerHTML = time +"秒后跳转页面"
time --;
}
}, 1000)
});
}
</script>
</head>
<body>
<button>倒计时跳转</button>
<div></div>
</body>
7.5 location对象常见方法:
location对象方法 | 返回值 |
---|---|
location.assign() | 跟href一样, 可以跳转页面(也称重定向页面) |
location.replace() | 替换当前页面, 因为不记录历史, 所以不能后退页面 |
location.reload() | 重新加载页面, 相当于刷新按钮, 如果参数为true, 则强制刷新 |
<button>assign</button>
<button>replace</button>
<button>reload</button>
<script>
var btns = document.querySelectorAll('button');
btn[0].addEventListener('click', function() {
// 记录浏览历史,所以可以实现后退功能
location.assign('http://www.baidu.com');
})
btn[1].addEventListener('click', function() {
// 不记录浏览历史,所以不可以实现后退功能
location.replace('http://www.baidu.com');
})
btn[2].addEventListener('click', function() {
// 刷新页面
location.reload(true);
})
</script>
8. navigator对象:
navigator 对象包含有关浏览器的信息,它有很多属性,最常用的是 userAgent,该属性可以返回由客户机发送服务器的 user-agent 头部的值。
下面前端代码可以判断用户那个终端打开页面,实现跳转
if((navigator.userAgent.match(/(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i))) {
window.location.href = ""; //手机
} else {
window.location.href = ""; //电脑
}
9 history对象
window对象给提供了一个 history对象,与浏览器历史记录进行交互。该对象包含用户(在浏览器窗口中)访问过的URL
history()对象方法 | 作用 |
---|---|
history.back() | 可以后退功能 |
history.fowward() | 前进功能 |
history.go(参数) | 前进/后退功能, 参数1, 前进1个页面; 参数-1, 后退一个页面 |
history对象一般在实际开发中比较少用,但是会在一些 OA 办公系统中见到
三、JS执行机制:
以下代码执行的结果是什么?
console.log(1);
setTimeout(function () {
console.log(3);
}, 1000);
console.log(2);
以下代码执行的结果是什么?
console.log(1);
setTimeout(function () {
console.log(3);
}, 0);
console.log(2);
1. JS 是单线程:
JavaScript语言的一大特点就是单线程, 也就是说, 同一时间只能做一件事. 这是因为JavaScript这门脚本语言诞生的使用所致----JavaScript是为了处理页面中用户交互, 以及操作DOM而诞生的.
单线程就意味着, 所有任务需要排队, 前一个任务结束, 才会执行后一个任务. 如果前一个任务耗时, 后一个任务就不得不等待.
这样导致的问题是: 如果JS执行时间过长, 这样就会造成页面渲染不连贯, 造成页面渲染加载阻塞的感觉.
2 同步任务和异步任务:
单线程导致的问题就是后面的任务等待前面任务完成,如果前面任务很耗时(比如读取网络数据), 后面任务不得不一直等待
为了解决这个问题,利用多核 CPU 的计算能力,HTML5 提出 Web Worker 标准,允许 JavaScript 脚本创建多个线程,但是子线程完全受主线程控制。于是,JS 中出现了同步任务和异步任务
同步
前一个任务结束后再执行后一个任务,程序的执行顺序与任务的排列顺序是一致的、同步的。比如做饭的同步做法:要烧水煮饭,等水开了(10分钟之后),再去切菜,炒菜。
异步
你在做一件事情时,因为这件事情会花费很长时间,在做这件事的同时,你还可以去处理其他事情。比如做饭的异步做法,在烧水的同时,利用这10分钟,去切菜,炒菜
他们本质区别: 这条流水线上各个流程的执行顺序不同;
JS中所有任务可以分成两种,一种是同步任务(synchronous),另一种是异步任务(asynchronous)。
同步任务指的是:
在主线程上排队执行的任务,只有前一个任务执行完毕,才能执行后一个任务;
异步任务指的是:
不进入主线程、而进入”任务队列”的任务,当主线程中的任务运行完了,才会从”任务队列”取出异步任务放入主线程执行。
3. JS执行机制(事件循环)
- 先执行执行栈中的同步任务;
- 异步任务(回调函数)放入任务队列中;
- 一旦执行栈中的所有同步任务执行完毕, 系统就会按次序读取任务对列中的异步任务, 于是被读取的异步任务结束登台状态, 进去执行栈, 开始执行;
由于主线程不断的重复获得任务,、执行任务、再获取任务、在执行, 所以这种机制被称为事件循环(event loop)