WebAPI编程(第三天,第四天)
- day03 - Web APIs
- 1.1. 节点操作
- 1.1.1 删除节点
- 1.1.2 案例:删除留言
- 1.1.3 复制(克隆)节点
- 1.1.4 案例:动态生成表格
- 1.1.5 创建元素的三种方式
- 1.1.6 innerTHML和createElement效率对比
- 1.2. DOM的核心总结
- 1.2.1. 创建
- 1.2.2. 增加
- 1.2.3. 删
- 1.2.4. 改
- 1.2.5. 查
- 1.2.6. 属性操作
- 1.2.7. 事件操作(重点)
- 1.3. 事件高级
- 1.3.1. 注册事件(2种方式)
- 1.3.2 事件监听
- addEventListener()事件监听(IE9以后支持)
- attacheEvent()事件监听(IE678支持)
- 事件监听兼容性解决方案
- 1.3.3. 删除事件(解绑事件)
- 1.3.4. DOM事件流
- 1.3.5. 事件对象
- 什么是事件对象
- 事件对象的使用
- 事件对象的兼容性处理
- 事件对象的属性和方法
- e.target 和 this 的区别
- 1.3.6 阻止默认行为
- 1.3.7 阻止事件冒泡
- 1.3.8 事件委托
- 什么是事件委托
- 事件委托的原理
- 事件委托的作用
- 1.4. 常用鼠标事件
- 1.4.1 案例:禁止选中文字和禁止右键菜单
- 1.4.2 鼠标事件对象
- 1.4.3 获取鼠标在页面的坐标
- 1.4.4 案例:跟随鼠标的天使
- day04 - Web APIs
- 1.1. 常用的键盘事件
- 1.1.1 键盘事件
- 1.1.2 键盘事件对象
- 1.1.3 案例:模拟京东按键输入内容
- 1.1.4 案例:模拟京东快递单号查询
- 1.2. BOM
- 1.2.1. 什么是BOM
- 1.2.2. BOM的构成
- 1.2.3. 顶级对象window
- 1.2.4. window对象的常见事件
- 页面(窗口)加载事件(2种)
- 调整窗口大小事件
- 1.2.5. 定时器(两种)
- setTimeout() 炸弹定时器
- 开启定时器
- 案例:5秒后关闭广告
- 停止定时器
- setInterval() 闹钟定时器
- 开启定时器
- 案例:倒计时
- 停止定时器
- 案例:发送短信倒计时
- 1.2.6. this指向问题
- 1.2.7. location对象
- 什么是 location 对象
- URL
- location 对象的属性
- 案例:5分钟自动跳转页面
- 案例:获取URL参数
- location对象的常见方法
- 1.2.8. navigator对象
- 1.2.9 history对象
- 1.3. JS执行机制
- 1.3.1 JS 是单线程
- 1.3.2 同步任务和异步任务
- 同步
- 异步
- 1.3.3 JS执行机制(事件循环)
- 1.3.4 代码思考题
day03 - Web APIs
学习目标:
能够使用removeChild()方法删除节点
能够完成动态生成表格案例
能够使用传统方式和监听方式给元素注册事件
能够说出事件流执行的三个阶段
能够在事件处理函数中获取事件对象
能够使用事件对象取消默认行为
能够使用事件对象阻止事件冒泡
能够使用事件对象获取鼠标的位置
能够完成跟随鼠标的天使案例
1.1. 节点操作
1.1.1 删除节点
node.removeChild() 方法从 node节点中删除一个子节点,返回删除的节点。
<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>
1.1.2 案例:删除留言
<textarea name="" id=""></textarea><button>发布</button><ul></ul><script>// 1. 获取元素var btn = document.querySelector('button');var text = document.querySelector('textarea');var ul = document.querySelector('ul');// 2. 注册事件btn.onclick = function() {if (text.value == '') {alert('您没有输入内容');return false;} else {// console.log(text.value);// (1) 创建元素var li = document.createElement('li');// 先有li 才能赋值li.innerHTML = text.value + "<a href='javascript:;'>删除</a>";// (2) 添加元素// ul.appendChild(li);ul.insertBefore(li, ul.children[0]);// (3) 删除元素 删除的是当前链接的li 它的父亲var as = document.querySelectorAll('a');for (var i = 0; i < as.length; i++) {as[i].onclick = function() {// 删除的是 li 当前a所在的li this.parentNode;ul.removeChild(this.parentNode);}}}}</script>
1.1.3 复制(克隆)节点
<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>
1.1.4 案例:动态生成表格
<script>// 1.先去准备好学生的数据var datas = [{name: '魏璎珞',subject: 'JavaScript',score: 100}, {name: '弘历',subject: 'JavaScript',score: 98}, {name: '傅恒',subject: 'JavaScript',score: 99}, {name: '明玉',subject: 'JavaScript',score: 88}, {name: '大猪蹄子',subject: 'JavaScript',score: 0}];// 2. 往tbody 里面创建行: 有几个人(通过数组的长度)我们就创建几行var tbody = document.querySelector('tbody');// 遍历数组for (var i = 0; i < datas.length; i++) { // 1. 创建 tr行var tr = document.createElement('tr');tbody.appendChild(tr);// 2. 行里面创建单元格td 单元格的数量取决于每个对象里面的属性个数 // 使用for in遍历学生对象for (var k in datas[i]) { // 创建单元格 var td = document.createElement('td');// 把对象里面的属性值 datas[i][k] 给 td td.innerHTML = datas[i][k];tr.appendChild(td);}// 3. 创建有删除2个字的单元格 var td = document.createElement('td');td.innerHTML = '<a href="javascript:;">删除 </a>';tr.appendChild(td);}// 4. 删除操作 开始 var as = document.querySelectorAll('a');for (var i = 0; i < as.length; i++) {as[i].onclick = function() {// 点击a 删除 当前a 所在的行(链接的爸爸的爸爸) node.removeChild(child) tbody.removeChild(this.parentNode.parentNode)}}</script>
1.1.5 创建元素的三种方式
<script>// 三种创建元素方式区别 // 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>
1.1.6 innerTHML和createElement效率对比
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>
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>
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>
1.2. DOM的核心总结
关于dom操作,我们主要针对于元素的操作。主要有创建、增、删、改、查、属性操作、事件操作。
1.2.1. 创建
1.2.2. 增加
1.2.3. 删
1.2.4. 改
1.2.5. 查
1.2.6. 属性操作
1.2.7. 事件操作(重点)
1.3. 事件高级
1.3.1. 注册事件(2种方式)
1.3.2 事件监听
addEventListener()事件监听(IE9以后支持)
eventTarget.addEventListener()方法将指定的监听器注册到 eventTarget(目标对象)上,当该对象触发指定的事件时,就会执行事件处理函数。
attacheEvent()事件监听(IE678支持)
eventTarget.attachEvent()方法将指定的监听器注册到 eventTarget(目标对象) 上,当该对象触发指定的事件时,指定的回调函数就会被执行。
<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);})// 3. attachEvent ie9以前的版本支持btns[2].attachEvent('onclick', function() {alert(11);})
</script>
事件监听兼容性解决方案
封装一个函数,函数中判断浏览器的类型:
1.3.3. 删除事件(解绑事件)
<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);}// 3. detachEventdivs[2].attachEvent('onclick', fn1);function fn1() {alert(33);divs[2].detachEvent('onclick', fn1);}</script>
1.3.4. DOM事件流
html中的标签都是相互嵌套的,我们可以将元素想象成一个盒子装一个盒子,document是最外面的大盒子。 当你单击一个div时,同时你也单击了div的父元素,甚至整个页面。那么是先执行父元素的单击事件,还是先执行div的单击事件 ???
比如:我们给页面中的一个div注册了单击事件,当你单击了div时,也就单击了body,单击了html,单击了document。
当时的2大浏览器霸主谁也不服谁! IE 提出从目标元素开始,然后一层一层向外接收事件并响应,也就是冒泡型事件流。 Netscape(网景公司)提出从最外层开始,然后一层一层向内接收事件并响应,也就是捕获型事件流。江湖纷争,武林盟主也脑壳疼!!!最终,w3c 采用折中的方式,平息了战火,制定了统一的标准 —--— 先捕获再冒泡。 现代浏览器都遵循了此标准,所以当事件发生时,会经历3个阶段。
DOM 事件流会经历3个阶段:
-
捕获阶段
-
当前目标阶段
-
冒泡阶段
我们向水里面扔一块石头,首先它会有一个下降的过程,这个过程就可以理解为从最顶层向事件发生的最具体元素(目标点)的捕获过程;之后会产生泡泡,会在最低点( 最具体元素)之后漂浮到水面上,这个过程相当于事件冒泡。
事件冒泡
<div class="father"><div class="son">son盒子</div></div><script>// onclick 和 attachEvent(ie) 在冒泡阶段触发// 冒泡阶段 如果addEventListener 第三个参数是 false 或者 省略 // son -> father ->body -> html -> documentvar son = document.querySelector('.son');// 给son注册单击事件son.addEventListener('click', function() {alert('son');}, false);// 给father注册单击事件var father = document.querySelector('.father');father.addEventListener('click', function() {alert('father');}, false);// 给document注册单击事件,省略第3个参数document.addEventListener('click', function() {alert('document');})</script>
事件捕获
<div class="father"><div class="son">son盒子</div></div><script>// 如果addEventListener() 第三个参数是 true 那么在捕获阶段触发// document -> html -> body -> father -> sonvar son = document.querySelector('.son');// 给son注册单击事件,第3个参数为trueson.addEventListener('click', function() {alert('son');}, true);var father = document.querySelector('.father');// 给father注册单击事件,第3个参数为truefather.addEventListener('click', function() {alert('father');}, true);// 给document注册单击事件,第3个参数为truedocument.addEventListener('click', function() {alert('document');}, true)</script>
1.3.5. 事件对象
什么是事件对象
事件发生后,跟事件相关的一系列信息数据的集合都放到这个对象里面,这个对象就是事件对象。
比如:
-
谁绑定了这个事件。
-
鼠标触发事件的话,会得到鼠标的相关信息,如鼠标位置。
-
键盘触发事件的话,会得到键盘的相关信息,如按了哪个键。
javascript"><!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>Document</title><style>div {width: 100px;height: 100px;background-color: pink;}</style>
</head><body><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>
</body></html>
事件对象的使用
事件触发发生时就会产生事件对象,并且系统会以实参的形式传给事件处理函数。
所以,在事件处理函数中声明1个形参用来接收事件对象。
事件对象的兼容性处理
事件对象本身的获取存在兼容问题:
-
标准浏览器中是浏览器给方法传递的参数,只需要定义形参 e 就可以获取到。
-
在 IE6~8 中,浏览器不会给方法传递参数,如果需要的话,需要到 window.event 中获取查找。
只要“||”前面为false, 不管“||”后面是true 还是 false,都返回 “||” 后面的值。
只要“||”前面为true, 不管“||”后面是true 还是 false,都返回 “||” 前面的值。
<div>123</div><script>var div = document.querySelector('div');div.onclick = function(e) {// 事件对象e = e || window.event;console.log(e);}</script>
事件对象的属性和方法
e.target 和 this 的区别
-
this 是事件绑定的元素(绑定这个事件处理函数的元素) 。
-
e.target 是事件触发的元素。
常情况下terget 和 this是一致的, 但有一种情况不同,那就是在事件冒泡时(父子元素有相同事件,单击子元素,父元素的事件处理函数也会被触发执行),这时候this指向的是父元素,因为它是绑定事件的元素对象,而target指向的是子元素,因为他是触发事件的那个具体元素对象。
<div>123</div><script>var div = document.querySelector('div');div.addEventListener('click', function(e) {// e.target 和 this指向的都是divconsole.log(e.target);console.log(this);});</script>
事件冒泡下的e.target和this
<ul><li>abc</li><li>abc</li><li>abc</li></ul><script>var ul = document.querySelector('ul');ul.addEventListener('click', function(e) {// 我们给ul 绑定了事件 那么this 就指向ul console.log(this); // ul// e.target 触发了事件的对象 我们点击的是li e.target 指向的就是liconsole.log(e.target); // li});</script>
javascript"><!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>Document</title><style>div {width: 100px;height: 100px;background-color: pink;}</style>
</head><body><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 e.target 指向的就是liconsole.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>
</body></html>
1.3.6 阻止默认行为
html中一些标签有默认行为,例如a标签被单击后,默认会进行页面跳转。
<a href="http://www.baidu.com">百度</a><script>// 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 = false;// 我们可以利用return false 也能阻止默认行为 没有兼容性问题return false;}</script>
1.3.7 阻止事件冒泡
事件冒泡本身的特性,会带来的坏处,也会带来的好处。
<div class="father"><div class="son">son儿子</div></div><script>var son = document.querySelector('.son');// 给son注册单击事件son.addEventListener('click', function(e) {alert('son');e.stopPropagation(); // stop 停止 Propagation 传播window.event.cancelBubble = true; // 非标准 cancel 取消 bubble 泡泡}, false);var father = document.querySelector('.father');// 给father注册单击事件father.addEventListener('click', function() {alert('father');}, false);// 给document注册单击事件document.addEventListener('click', function() {alert('document');})</script>
阻止事件冒泡的兼容性处理
1.3.8 事件委托
事件冒泡本身的特性,会带来的坏处,也会带来的好处。
什么是事件委托
把事情委托给别人,代为处理。
事件委托也称为事件代理,在 jQuery 里面称为事件委派。
说白了就是,不给子元素注册事件,给父元素注册事件,把处理代码在父元素的事件中执行。
事件委托的原理
给父元素注册事件,利用事件冒泡,当子元素的事件触发,会冒泡到父元素,然后去控制相应的子元素。
事件委托的作用
-
我们只操作了一次 DOM ,提高了程序的性能。
-
动态新创建的子元素,也拥有事件。
<ul><li>知否知否,点我应有弹框在手!</li><li>知否知否,点我应有弹框在手!</li><li>知否知否,点我应有弹框在手!</li><li>知否知否,点我应有弹框在手!</li><li>知否知否,点我应有弹框在手!</li></ul><script>// 事件委托的核心原理:给父节点添加侦听器, 利用事件冒泡影响每一个子节点var ul = document.querySelector('ul');ul.addEventListener('click', function(e) {// e.target 这个可以得到我们点击的对象e.target.style.backgroundColor = 'pink';})</script>
1.4. 常用鼠标事件
javascript"><!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>Document</title>
</head><body>我是一段不愿意分享的文字<script>// 1. contextmenu 我们可以禁用右键菜单document.addEventListener('contextmenu', function(e) {e.preventDefault();})// 2. 禁止选中文字 selectstartdocument.addEventListener('selectstart', function(e) {e.preventDefault();})</script>
</body></html>
1.4.1 案例:禁止选中文字和禁止右键菜单
<body>我是一段不愿意分享的文字<script>// 1. contextmenu 我们可以禁用右键菜单document.addEventListener('contextmenu', function(e) {e.preventDefault();})// 2. 禁止选中文字 selectstartdocument.addEventListener('selectstart', function(e) {e.preventDefault();})</script>
</body>
1.4.2 鼠标事件对象
1.4.3 获取鼠标在页面的坐标
<script>// 鼠标事件对象 MouseEventdocument.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>
1.4.4 案例:跟随鼠标的天使
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>Document</title><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></html>
day04 - Web APIs
学习目标:
能够说出常用的3-5个键盘事件
能够知道如何获取当前键盘按下的是哪个键
能够知道浏览器的顶级对象window
能够使用window.onload事件
能够使用window.onresize事件
能够说出两种定时器的区别
能够使用location对象的href属性完成页面之间的跳转
能够使用location对象获取url中的参数部分
能够使用history提供的方法实现页面刷新
1.1. 常用的键盘事件
1.1.1 键盘事件
<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>
1.1.2 键盘事件对象
使用keyCode属性判断用户按下哪个键
<script>// 键盘事件对象中的keyCode属性可以得到相应键的ASCII码值// 1. 我们的keyup 和keydown事件不区分字母大小写 a 和 A 得到的都是65// 2. 我们的keypress 事件 区分字母大小写 a 97 和 A 得到的是65document.addEventListener('keyup', function(e) {// console.log(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>
1.1.3 案例:模拟京东按键输入内容
当我们按下 s 键, 光标就定位到搜索框(文本框获得焦点)。
注意:触发获得焦点事件,可以使用 元素对象.focus()
<input type="text"><script>// 获取输入框var search = document.querySelector('input');// 给document注册keyup事件document.addEventListener('keyup', function(e) {// 判断keyCode的值if (e.keyCode === 83) {// 触发输入框的获得焦点事件search.focus();}})</script>
1.1.4 案例:模拟京东快递单号查询
要求:当我们在文本框中输入内容时,文本框上面自动显示大字号的内容。
<div class="search"><div class="con">123</div><input type="text" placeholder="请输入您的快递单号" class="jd"></div><script>// 获取要操作的元素var con = document.querySelector('.con');var jd_input = document.querySelector('.jd');// 给输入框注册keyup事件jd_input.addEventListener('keyup', function() {// 判断输入框内容是否为空if (this.value == '') {// 为空,隐藏放大提示盒子con.style.display = 'none';} else {// 不为空,显示放大提示盒子,设置盒子的内容con.style.display = 'block';con.innerText = this.value;}})// 给输入框注册失去焦点事件,隐藏放大提示盒子jd_input.addEventListener('blur', function() {con.style.display = 'none';})// 给输入框注册获得焦点事件jd_input.addEventListener('focus', function() {// 判断输入框内容是否为空if (this.value !== '') {// 不为空则显示提示盒子con.style.display = 'block';}})</script>
1.2. BOM
1.2.1. 什么是BOM
BOM(Browser Object Model)即浏览器对象模型,它提供了独立于内容而与浏览器窗口进行交互的对象,其核心对象是 window。
BOM 由一系列相关的对象构成,并且每个对象都提供了很多方法与属性。
BOM 缺乏标准,JavaScript 语法的标准化组织是 ECMA,DOM 的标准化组织是 W3C,BOM 最初是Netscape 浏览器标准的一部分。
1.2.2. BOM的构成
BOM 比 DOM 更大,它包含 DOM。
1.2.3. 顶级对象window
1.2.4. window对象的常见事件
页面(窗口)加载事件(2种)
第1种
window.onload 是窗口 (页面)加载事件,当文档内容完全加载完成会触发该事件(包括图像、脚本文件、CSS 文件等), 就调用的处理函数。
第2种
DOMContentLoaded 事件触发时,仅当DOM加载完成,不包括样式表,图片,flash等等。
IE9以上才支持!!!
如果页面的图片很多的话, 从用户访问到onload触发可能需要较长的时间, 交互效果就不能实现,必然影响用户的体验,此时用 DOMContentLoaded 事件比较合适。
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>Document</title><script>// window.onload = function() {// var btn = document.querySelector('button');// btn.addEventListener('click', function() {// alert('点击我');// })// }// window.onload = function() {// alert(22);// }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);})// load 等页面内容全部加载完毕,包含页面dom元素 图片 flash css 等等// DOMContentLoaded 是DOM 加载完毕,不包含图片 falsh css 等就可以执行 加载速度比 load更快一些</script>
</head><body><button>点击</button></body></html>
调整窗口大小事件
window.onresize 是调整窗口大小加载事件, 当触发时就调用的处理函数。
注意:
-
只要窗口大小发生像素变化,就会触发这个事件。
-
我们经常利用这个事件完成响应式布局。 window.innerWidth 当前屏幕的宽度
<script>// 注册页面加载事件window.addEventListener('load', function() {var div = document.querySelector('div');// 注册调整窗口大小事件window.addEventListener('resize', function() {// window.innerWidth 获取窗口大小console.log('变化了');if (window.innerWidth <= 800) {div.style.display = 'none';} else {div.style.display = 'block';}})})</script><div></div>
1.2.5. 定时器(两种)
window 对象给我们提供了 2 个非常好用的方法-定时器。
-
setTimeout()
-
setInterval()
setTimeout() 炸弹定时器
开启定时器
普通函数是按照代码顺序直接调用。
简单理解: 回调,就是回头调用的意思。上一件事干完,再回头再调用这个函数。
例如:定时器中的调用函数,事件处理函数,也是回调函数。以前我们讲的 element.onclick = function(){} 或者 element.addEventListener(“click”, fn); 里面的 函数也是回调函数。
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>Document</title>
</head><body><script>// 1. setTimeout // 语法规范: window.setTimeout(调用函数, 延时时间);// 1. 这个window在调用的时候可以省略// 2. 这个延时时间单位是毫秒 但是可以省略,如果省略默认的是0// 3. 这个调用函数可以直接写函数 还可以写 函数名 还有一个写法 '函数名()'// 4. 页面中可能有很多的定时器,我们经常给定时器加标识符 (名字)// setTimeout(function() {// console.log('时间到了');// }, 2000);function callback() {console.log('爆炸了');}var timer1 = setTimeout(callback, 3000);var timer2 = setTimeout(callback, 5000);// setTimeout('callback()', 3000); // 我们不提倡这个写法</script>
</body></html>
案例:5秒后关闭广告
<body><img src="images/ad.jpg" alt="" class="ad"><script>// 获取要操作的元素var ad = document.querySelector('.ad');// 开启定时器setTimeout(function() {ad.style.display = 'none';}, 5000);</script>
</body>
停止定时器
clearTimeout(timer)
<button>点击停止定时器</button><script>var btn = document.querySelector('button');// 开启定时器var timer = setTimeout(function() {console.log('爆炸了');}, 5000);// 给按钮注册单击事件btn.addEventListener('click', function() {// 停止定时器clearTimeout(timer);})</script>
setInterval() 闹钟定时器
开启定时器
<script>// 1. setInterval // 语法规范: window.setInterval(调用函数, 延时时间);setInterval(function() {console.log('继续输出');}, 1000);// 2. setTimeout 延时时间到了,就去调用这个回调函数,只调用一次 就结束了这个定时器// 3. setInterval 每隔这个延时时间,就去调用这个回调函数,会调用很多次,重复调用这个函数</script>
案例:倒计时
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>Document</title><style>div {margin: 200px;}span {display: inline-block;width: 80px;height: 40px;background-color: #333;font-size: 20px;color: #fff;text-align: center;line-height: 40px;}</style>
</head><body><div><span class="hour">1</span><span class="minute">2</span><span class="second">3</span></div><script>// 1. 获取元素 var hour = document.querySelector('.hour'); // 小时的黑色盒子var minute = document.querySelector('.minute'); // 分钟的黑色盒子var second = document.querySelector('.second'); // 秒数的黑色盒子var inputTime = +new Date('2019-5-1 18:00:00'); // 返回的是用户输入时间总的毫秒数countDown(); // 我们先调用一次这个函数,防止第一次刷新页面有空白 // 2. 开启定时器setInterval(countDown, 1000);function countDown() {var nowTime = +new Date(); // 返回的是当前时间总的毫秒数var times = (inputTime - nowTime) / 1000; // times是剩余时间总的秒数 var h = parseInt(times / 60 / 60 % 24); //时h = h < 10 ? '0' + h : h;hour.innerHTML = h; // 把剩余的小时给 小时黑色盒子console.log(' hour.innerHTML', hour.innerHTML)var m = parseInt(times / 60 % 60); // 分m = m < 10 ? '0' + m : m;minute.innerHTML = m;console.log(' minute.innerHTML', minute.innerHTML)var s = parseInt(times % 60); // 当前的秒s = s < 10 ? '0' + s : s;second.innerHTML = s;console.log(' second.innerHTML', second.innerHTML)}</script>
</body></html
停止定时器
clearInterval(timer);
javascript"><!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>Document</title>
</head><body><button class="begin">开启定时器</button><button class="stop">停止定时器</button><script>var begin = document.querySelector('.begin');var stop = document.querySelector('.stop');var timer = null; // 全局变量 null是一个空对象begin.addEventListener('click', function() {timer = setInterval(function() {console.log('ni hao ma');}, 1000);})stop.addEventListener('click', function() {clearInterval(timer);})</script>
</body></html>
案例:发送短信倒计时
点击按钮后,该按钮60秒之内不能再次点击,防止重复发送短信。
手机号码: <input type="number"> <button>发送</button><script>var btn = document.querySelector('button');// 全局变量,定义剩下的秒数var time = 3; // 注册单击事件btn.addEventListener('click', function() {// 禁用按钮btn.disabled = true;// 开启定时器var timer = setInterval(function() {// 判断剩余秒数if (time == 0) {// 清除定时器和复原按钮clearInterval(timer);btn.disabled = false;btn.innerHTML = '发送';} else {btn.innerHTML = '还剩下' + time + '秒';time--;}}, 1000);});</script>
1.2.6. this指向问题
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>
1.2.7. location对象
什么是 location 对象
URL
location 对象的属性
案例:5分钟自动跳转页面
<button>点击</button><div></div><script>var btn = document.querySelector('button');var div = document.querySelector('div');btn.addEventListener('click', function() {// console.log(location.href);location.href = 'http://www.itcast.cn';})var timer = 5;setInterval(function() {if (timer == 0) {location.href = 'http://www.itcast.cn';} else {div.innerHTML = '您将在' + timer + '秒钟之后跳转到首页';timer--;}}, 1000);</script>
案例:获取URL参数
<div></div><script>console.log(location.search); // ?uname=andy// 1.先去掉? substr('起始的位置',截取几个字符);var params = location.search.substr(1); // uname=andyconsole.log(params);// 2. 利用=把字符串分割为数组 split('=');var arr = params.split('=');console.log(arr); // ["uname", "ANDY"]var div = document.querySelector('div');// 3.把数据写入div中div.innerHTML = arr[1] + '欢迎您';</script>
location对象的常见方法
<button>点击</button><script>var btn = document.querySelector('button');btn.addEventListener('click', function() {// 记录浏览历史,所以可以实现后退功能// location.assign('http://www.itcast.cn');// 不记录浏览历史,所以不可以实现后退功能// location.replace('http://www.itcast.cn');location.reload(true);})</script>
1.2.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 = ""; //电脑}
1.2.9 history对象
window对象给我们提供了一个 history对象,与浏览器历史记录进行交互。该对象包含用户(在浏览器窗口中)访问过的URL。
javascript"><!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>Document</title>
</head><body><a href="list.html">点击我去往列表页</a><button>前进</button><script>var btn = document.querySelector('button');btn.addEventListener('click', function() {// history.forward();history.go(1);})</script>
</body></html>
javascript"><!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>Document</title>
</head><body><a href="index.html">点击我去往首页</a><button>后退</button><script>var btn = document.querySelector('button');btn.addEventListener('click', function() {// history.back();history.go(-1);})</script>
</body></html>
history对象一般在实际开发中比较少用,但是会在一些 OA 办公系统中见到。
1.3. 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.3.1 JS 是单线程
单线程就意味着,所有任务需要排队,前一个任务结束,才会执行后一个任务。如果前一个任务耗时很长,后一个任务就不得不一直等着。这样所导致的问题是: 如果 JS 执行的时间过长,这样就会造成页面的渲染不连贯,导致页面渲染加载阻塞的感觉。
1.3.2 同步任务和异步任务
单线程导致的问题就是后面的任务等待前面任务完成,如果前面任务很耗时(比如读取网络数据),后面任务不得不一直等待!!
为了解决这个问题,利用多核 CPU 的计算能力,HTML5 提出 Web Worker 标准,允许 JavaScript 脚本创建多个线程,但是子线程完全受主线程控制。于是,JS 中出现了同步任务和异步任务。
同步
前一个任务结束后再执行后一个任务,程序的执行顺序与任务的排列顺序是一致的、同步的。比如做饭的同步做法:我们要烧水煮饭,等水开了(10分钟之后),再去切菜,炒菜。
异步
你在做一件事情时,因为这件事情会花费很长时间,在做这件事的同时,你还可以去处理其他事情。比如做饭的异步做法,我们在烧水的同时,利用这10分钟,去切菜,炒菜。
JS中所有任务可以分成两种,一种是同步任务(synchronous),另一种是异步任务(asynchronous)。
同步任务指的是:
在主线程上排队执行的任务,只有前一个任务执行完毕,才能执行后一个任务;
异步任务指的是:
不进入主线程、而进入”任务队列”的任务,当主线程中的任务运行完了,才会从”任务队列”取出异步任务放入主线程执行。
javascript"><!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>Document</title>
</head><body><script>// 第一个问题// console.log(1);// setTimeout(function() {// console.log(3);// }, 1000);// console.log(2);// 2. 第二个问题// console.log(1);// setTimeout(function() {// console.log(3);// }, 0);// console.log(2);// 3. 第三个问题console.log(1);document.onclick = function() {console.log('click');}console.log(2);setTimeout(function() {console.log(3)}, 3000)</script>
</body></html>
1.3.3 JS执行机制(事件循环)
1.3.4 代码思考题
console.log(1);document.onclick = function() {console.log('click');}setTimeout(function() {console.log(3)}, 3000)console.log(2);