Web APIs
1. Web APIs 和 JS 基础关联性
- Web APIs 是 JS 的应用,大量使用 JS 基础语法做交互效果
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0F2D2Ceo-1668609195843)(https://gitee.com/colohh/image_bed/raw/master/img/JS%E7%9A%84%E7%BB%84%E6%88%90.png)]
2. API 和Web API
- API (应用程序编程接口)一般是一些预定义的函数,是给程序员提供的一种工具,以便更轻松实现功能
- Web API 是浏览器提供的一套操作浏览器功能和页面元素的API(BOM 和 BOM),主要针对浏览器做交互效果
- Web API 一般都有输入和输出(函数的传参和返回值),Web API 很对都是方法(函数)
3. DOM
3.1 DOM 简介
-
文档对象模型(DOM),处理可标记语言(HTML , XML)的编程接口
-
可以改变网页的内容、结构和样式
-
DOM 树
DOM 把以下内容都看作是对象
-
文档:一个页面就是一个文档,DOM 中用 document 表示
-
元素:页面中的所有标签都是元素,DOM 中用 element 表示
-
节点:网页中所有内容都是节点(标签、属性、文本、注释等)DOM 中用 node 表示
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AyFu8AfF-1668609195844)(https://gitee.com/colohh/image_bed/raw/master/img/DOM%E6%A0%91.png)]
-
3.2 获取元素
3.2.1 根据 ID 获取
-
getElementById(id)
let element = document.getElementById(id);
-
返回的是一个元素对象
-
get:获得 ;element:元素 ;by:通过 – 驼峰命名法
-
参数 id 是大小写敏感的字符串
-
因为我们文档页面从上往下加载,所以先得有标签 所以我们script写到标签的下面
-
console.dir 打印我们返回的元素对象 更好的查看里面的属性和方法
<div id="time">2019-9-9</div> <script> let timer = document.getElementById('time'); console.log(timer);// <div id="time">2019-9-9</div> console.log(typeof timer);// Object console.dir(timer);// time 的属性和方法 </script>
-
3.2.2 根据标签名获取
-
getElementsByTagName(标签名)
let lis = document.getElementsByTagName('标签名');
-
返回的是带有指定标签名的对象的集合,以伪数组的形式存储的
console.log(lis); console.log(lis[0]);
-
得到的元素是动态的
-
我们想要依次打印里面的元素对象我们可以采取遍历的方式
for (let i = 0; i < lis.length; i++) { console.log(lis[i]); }
-
如果页面中只有一个li 返回的还是伪数组的形式
-
如果页面中没有这个元素 返回的是空的伪数组的形式
-
element.getElementsByTagName(‘标签名’);父元素必须是指定的单个元素,获取的时候不包括父元素自己
let ol = document.getElementById('ol'); console.log(ol.getElementsByTagName('li'));
-
3.2.3 通过 HTML5 新增的方法获取
(1)getElementsByClassName(类名)
-
根据类名获得某些元素集合
let boxs = document.getElementsByClassName('box'); console.log(boxs);
(2)querySelector()
-
返回指定选择器的第一个元素对象
-
返回指定选择器的第一个元素对象 切记 里面的选择器需要加符号
- querySelector(‘.类名’)
- querySelector(‘#ID名’)
- querySelector(‘标签名’)
let firstBox = document.querySelector('.box'); console.log(firstBox); let nav = document.querySelector('#nav'); console.log(nav); var li = document.querySelector('li'); console.log(li);
-
(3)querySelectorAll()
- 返回指定选择器的所有元素对象集合
3.2.4 获取特殊元素
(1)获取 body 标签
let bodyEle = document.body;
console.log(bodyEle);// 元素
console.dir(bodyEle);// 属性方法
(2)获取 head 标签
let htmlEle = document.documentElement;
console.log(htmlEle);
3.3 事件基础
3.3.1 事件概述
- JS 使我们有能力创建动态页面,而事件是可以被 JavaScript 侦测到的行为,触发相应的一种机制
3.3.2 事件三要素(执行时间的步骤)
-
事件源(事件被触发的对象)
- 获得事件对象
let btn = document.getElementById('btn');
-
事件类型(如何触发 什么事件 比如鼠标点击(onclick) 还是鼠标经过 还是键盘按下)
-
事件处理程序
-
通过一个函数赋值的方式完成
btn.onclick = function() { alert('点秋香'); }
-
3.3.3 常见的鼠标事件
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BWh3aesJ-1668609195845)(https://gitee.com/colohh/image_bed/raw/master/img/%E5%B8%B8%E8%A7%81%E7%9A%84%E9%BC%A0%E6%A0%87%E4%BA%8B%E4%BB%B6.png)]
3.4 操作元素
3.4.1 改变元素内容
(1)innerText
替换从开始到终止位置的内容,但他去除 html 标签,同时空格和换行也会去掉
-
获取元素
let btn = document.querySelector('button'); let div = document.querySelector('div'); let p = document.querySelector('p');
-
注册事件(元素可以不添加事件)
btn.onclick = function(){ // div.innerText = '2019-6-6'; div.innerText = getDate();// JS 基础中封装的函数 } // 元素可以不添加事件 p.innerText = getDate();
(2)innerHTML
替换从开始到终止位置的内容,保留 html 标签,同时也保留空格和换行
(3)innerText 和 innerHTML 的区别
-
innerText 不识别html标签,同时空格和换行也会去掉
div.innerText = '<strong>今天是:</strong> 2019';//
-
innerHTML 识别html标签,同时也保留空格和换行
div.innerText = '<strong>今天是:</strong> 2019';//
3.4.2 操作常见元素属性
格式:元素.属性= ’ ’
常用的元素属性
- src、href
- id、alt、title
-
获取元素
let ldh = document.getElementById('ldh'); let zxy = document.getElementById('zxy'); let img = document.querySelector('img');
-
注册事件 处理程序
zxy.onclick = function() { img.src = 'images/zxy.jpg'; img.title = '张学友思密达'; } ldh.onclick = function() { img.src = 'images/ldh.jpg'; img.title = '刘德华'; }
3.4.3 操作表单元素属性
常用的表单元素属性:
- type、value、checked、selected、disabled
-
获取元素
let btn = document.querySelector('button'); let input = document.querySelector('input');
-
注册事件 处理程序
-
表单里面的值 文字内容是通过 value 来修改的
btn.onclick = function() { input.value = '被点击了'; }
-
如果想要某个表单被禁用 不能再点击用 disabled
this.disabled = true;// this 指向的是事件函数的调用者 btn
-
3.4.4 操作元素样式属性
我们可以通过 JS 修改元素的大小、颜色、位置等样式
-
element==.style==
-
行内样式:适合于样式较少的情况,CSS权重比较高
-
获取元素
let div = document.querySelector('div')
-
注册事件 处理程序
div.onclick = function() { //div.style this.style.backgroundColor = 'purple';//点击修改颜色 this.style.width = '250px';//修改宽度 this.style.display = 'none';//点击隐藏 }
-
-
element.className
-
类名样式:className更改元素的样式 适合于样式较多或者功能复杂的情况
-
className 会直接更改、覆盖原来的类名
如果想要保留原先的类名,可以在原来的类名后面加上空格和新的类名(多类名选择器)
-
在 CSS 中 写一个 .change 样式
.change { background-color: purple; color: #fff; font-size: 25px; margin-top: 100px; }
-
获取元素 注册事件 处理程序
<div class="first">文本</div> <script> var test = document.querySelector('div'); test.onclick = function() { this.className = 'first change';// 多类名选择器 } </script>
-
3.4.6 排他思想
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9gFfZhPh-1668609195846)(https://gitee.com/colohh/image_bed/raw/master/img/%E6%8E%92%E4%BB%96%E6%80%9D%E6%83%B3.png)]
如果有同一组元素,我们想要某一个元素实现某种样式,需要用到循环的排他思想算法:
- 所有元素全部清除样式
- 给当前元素设置样式
- 注意顺序不能颠倒,先干掉其他人,再设置自己
<button>按钮1</button>
<button>按钮2</button>
<button>按钮3</button>
<button>按钮4</button>
<button>按钮5</button>
<script>
//1.获取所有元素
let btns = document.querySelectorAll('button');
// btns 得到的是伪数组 里面的每一个元素 btns[i]
for(let i = 0; i < btns.length; i++) {
btns[i].onclick = function() {
// (1)我们先把所有的按钮背景颜色全部去掉
for(let j = 0; j < btns.length; j++) {
btns[j].style.backgroundColor = '';
}
// (2)然后再把选中的按钮背景颜色改为粉色
this.style.backgroundColor = 'pink';
}
}
</script>
3.4.7 自定义属性的操作
自定义属性的目的:为了保存并使用一些不用保存在数据库中直接保存在页面中的数据。
(1)获取属性值
-
element.属性
- 获取内置属性值(元素本身自带的)
<div id="box" index="1"></div> <script> let box = document.querySelector('div'); // 打印box属性值 id console.log(div.id); </script>
-
获取自定义属性
-
兼容性获取 element.getAttribute(‘data-index’)
- 主要获取我们自己添加自定义的属性值(index)
// 打印box属性值 index console.log(div.getAttribute('data-index'));
-
H5 新增方法 element.dataset.index 或 element.dataset[‘index’]
-
它只能获取 data- 开头的
-
dataset 是一个集合 里面存放了所有以 data 开头的自定义属性
-
如果自定义属性里面有多个 - 连接的单词,我们获取的时候采取 驼峰命名法
<div id="box" data-index="1" data-list-name="andy"></div> <script> console.log(div.dataset.index); console.log(div.dataset['index']); console.log(div.dataset.listName); console.log(div.dataset['listName']); </script>
-
-
(2)设置属性值
-
element.属性 = ‘值’
- 设置内置属性值
div.id = 'text'; div.className = 'navs';// 修改类名 class
-
element.setAttribute(‘属性’,‘值’)
- 主要设置自定义属性
- H5 规定自定义属性要以 data-开头 作为属性名并赋值
<div></div> <script> div.setAttribute('data-index',0); div.setAttribute('class','footer');// 修改类名 class </script>
(3)移除属性
-
element.removeAttribute(‘属性’)
div.removeAttribute('index')
3.5 节点操作
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TKHWL1qz-1668609195846)(https://gitee.com/colohh/image_bed/raw/master/img/%E8%8E%B7%E5%8F%96%E5%85%83%E7%B4%A0.png)]
3.5.1 节点概述
-
网页中所有内容都是节点(标签、属性、文本、注释等)
-
HTML DOM 书中的所有节点均可通过 JavaScript 进行访问,所有 HTML 元素(节点)均可被修改,也可以创建或删除
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zxYW3m5v-1668609195847)(https://gitee.com/colohh/image_bed/raw/master/img/DOM%E6%A0%91.png)]
-
一般地,节点至少拥有 nodeType(节点类型)、nodeName(节点名称)、==nodeValue(节点值)==这三个基本属性。
- nodeType 的值
- 元素节点为 1
- 属性节点为 2
- 文本节点为 3(文本节点包括文字、空格、换行等)
- nodeType 的值
3.5.2 节点层级
(1)父级节点
-
element.parentNode
-
得到的是离 element 最近的父节点
<div class="box"> <span class="erweima">×</span> </div> <script> let erweima = document.querySelector('.erweima'); // 如果找不到父节点就返回 null console.log('erweima.parentNode');// 获取box </script>
-
(2)子节点
① 获取子节点
-
parentNode.childNodes(不提倡)
-
childNodes 得到的所有子节点包括:元素节点、文本节点等等。如果我们只想要获得元素节点,则需要专门处理:
<ul> <li></li> <li></li> <li></li> </ul> <script> // 获取元素 let ul = document.querySelector('ul'); console.log(ul.childNode); // 只保留元素节点 for(let i = 0; i < ul.childNodes.length; i++){ if(ul.childNodes[i].nodeType == 1) { console.log(ul.childNodes[i]); } } </script>
-
-
parentNode.children
-
它是一个只读属性,返回所有的子元素节点。也是我们实际开发常用的。
console.log(ul.children);
-
② 获取第一个和最后一个子节点
-
第一个子节点
-
parentNode.firstChild:包括 文本节点 和 元素节点
let ul = document.querySelector('ul'); console.log(ul.firstChild);
-
parentNode.firstElementChild 只返回元素节点
console.log(ul.firstElementChild;
-
parentNode.children[]
console.log(ul.children[0]);
-
-
最后一个子节点
-
parentNode.lastChild:包括 文本节点 和 元素节点
let ul = document.querySelector('ul'); console.log(ul.lastChild);
-
parentNode.lastElementChild 只返回元素节点
console.log(ul.firstElementChild;
-
parentNode.children[]
console.log(ul.children[ul.children.length - 1]);
-
(3)兄弟节点
-
下一个兄弟节点
-
node.nextSibling:包含元素节点 或者 文本节点等等
<div>我是div</div> <span>我是span</span> <script> var div = document.querySelector('div'); console.log(div.nextSibling); </script>
-
node.nextElementSibling:得到下一个兄弟元素节点
console.log(div.nextElementSibling);
-
-
上一个兄弟节点
-
node.previousSibling:包含元素节点 或者 文本节点等等
console.log(div.previousSibling);
-
node.previousElementSibling:得到上一个兄弟元素节点
console.log(div.previousElementSibling);
-
3.5.3 创建节点
先创建 再添加位置
-
动态创建元素节点
-
document.createElement(‘tagName’);
- 创建多个元素效率稍微低一些,但是结构更清晰
let li = document.createElement('li');
-
document.innerHTML(‘tagName’);
- 创建多个元素效率更高(前提是不要拼接字符串,采取数组形式拼接),结构稍微复杂
let inner = document.querySelector('.inner'); inner.innerHTML = '<a href='#'>百度</a>'
-
document.write(‘tagName’);
- 如果页面文档流加载完毕,再调用这句话会导致页面重绘
-
添加节点
-
node.appendChild(child) :将 一个节点(child)追加到指定父节点(node)列表末尾
-
appendChild 不支持追加字符串的子元素,insertAdjacentHTML 支持追加字符串的元素
let ul = document.querySelector('ul'); ul.appendChild(li);
-
node.insertBefore(child, 指定元素):将 一个节点(child)追加到指定子节点前面
let lili = document.createElement('li'); ul.insertBefore(lili, ul.children[0]);
-
3.5.4 删除节点
-
node.removeChild(child)
-
从 DOM 中删除一个子结点,返回删除的节点
let ul = document.querySelector('ul'); ul.removeChild(ul.children[0]);
-
3.5.5 复制节点(克隆节点)
先克隆,再添加位置
-
克隆指定节点
-
node.cloneNode()
-
若括号参数为空或者为false,则是浅拷贝,即只克隆复制节点本身,不克隆里面的子节点;
-
若想要克隆标签及内容,只需在括号里写 true :node.cloneNode(true)
let ul = document.querySelector('ul'); let lili = ul.children[0].cloneNode();
-
-
添加节点位置
-
同 3.5.3 添加节点(有两种方法)
ul.appendChild(lili)
-
3.5.6 创建并插入节点 insertAdjacentHTML()
-
insertAdjacentHTML() 方法将指定的文本解析为 HTML 或 XML,并将结果节点插入到DOM树中的指定位置。它不会重新解析它正在使用的元素,因此它不会破坏元素内的现有元素。这避免了额外的序列化步骤,使其比直接使用innerHTML操作更快。
-
利用 insertAdjacentHTML() 可以直接把字符串格式添加到父元素中
-
语法:
-
position 是插入的位置
-
text 是要被解析为 HTML 和 XML,并插入到 DOM 树中的字符串
element.insertAdjacentHTML(position,text);
-
-
参数
- ‘beforebegin’
- 元素自身的前面
- ‘afterbegin’
- 插入元素内部的第一个子节点之前
- ‘beforeend’
- 插入元素内部的最后一个子节点之后
- ‘afterend’
- 元素自身的后面
- ‘beforebegin’
-
代码实例:
let html = '<div id="two">two</div>'; div.insertAdjacentHTML('beforeend',html);
3.6 事件高级
3.6.1 注册事件(绑定事件)
给元素添加事件,称为注册事件。
注册事件有两种方式:传统方式和方法监听注册方式
(1)传统注册方式
-
利用 on 开头的事件
-
特点:注册事件的唯一性:同一个元素同一个事件只能执行一次
<button onclick="alert('hi~')"></button> <script> btn.onclick = function(){ alert('hi~') } </script>
(2)方法监听注册方式
-
w3c 标准 推荐方式
-
特点:同一个元素同一个事件可以注册多个监听器,按照注册顺序依次执行
-
==addEventListener()==它是一种方法
eventTarget.addEventListenner(type,listener[,useCapture])
-
type:事件类型字符串,比如 click、mouseover,注意这里没有on哦
-
listener:事件处理函数,事件发生时,会调用该监听函数
-
useCapture:可选参数,是一个布尔值,默认为 false
btn.addEventListener('click',function(){ alert('hi~') })
-
3.6.2 删除事件(解绑事件)
(1)传统方式删除事件
-
eventTarget.onclick = null;
let div = document.querySelector('div'); div.onclick = function() { alert('hi~'); // 删除事件 div.onclick = null; }
(2)方法监听注册方式删除事件
-
eventTarget.removeEventListener(type,listener[,useCapture]);
btn.addEventListener('click',fn);// 里面的 fn 不需要调用 所以不加小括号 function fn() { alert('hi~'); // 删除事件 btn.removeEventListener('click',fn); }
3.6.3 DOM事件流
-
事件流描述的是从页面中接收事件的顺序
-
事件发生时会在元素节点中按照特定的顺序传播,这个传播过程即DOM事件流
-
DOM事件流分为三个阶段:
- 捕获阶段
- 当前目标阶段
- 冒泡阶段
- 有些事件是没有冒泡的,比如 onblur、onfocus、onmouseenter、onmouseleave
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-duGFu7Aw-1668609195848)(https://gitee.com/colohh/image_bed/raw/master/img/DOM%E4%BA%8B%E4%BB%B6%E6%B5%81.png)]
- 有些事件是没有冒泡的,比如 onblur、onfocus、onmouseenter、onmouseleave
-
代码验证
-
JS 代码中只能执行捕获或者冒泡其中的一个阶段。
-
onclick 和 attachEvent(ie) 只能得到冒泡阶段。
-
捕获阶段
-
如果addEventListener 第三个参数是 true 那么则处于捕获阶段
-
document -> html -> body -> father -> son
// 先输出 father 再输出 son let son = document.querySelector('.son'); son.addEventListener('click', function() { alert('son'); }, true); let father = document.querySelector('.father'); father.addEventListener('click', function() { alert('father'); }, true);
-
-
冒泡阶段
-
如果addEventListener 第三个参数是 false 或者 省略 那么则处于冒泡阶段
-
son -> father ->body -> html -> document
// 先输出 son 再输出 father 最后是 document let son = document.querySelector('.son'); son.addEventListener('click', function() { alert('son'); }, false); let father = document.querySelector('.father'); father.addEventListener('click', function() { alert('father'); }, false); document.addEventListener('click', function() { alert('document'); })
-
-
3.6.4 事件对象
div.onclick = function(event) {}
-
event 就是一个事件对象 写到我们侦听函数的小括号里面 当形参来看
-
事件对象只有有了事件才会存在,它是系统给我们自动创建的,不需要我们传递参数
-
事件对象是跟事件相关的一系列相关数据的集合(属性和方法):比如鼠标点击里面就包含了鼠标的相关信息,鼠标坐标等;如果是键盘事件里面就包含的键盘事件的信息,比如判断用户按下了那个键
-
事件对象可以自己命名 比如 event 、 evt、 e
-
事件对象的常见属性和方法:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iVBsl4mB-1668609195848)(https://gitee.com/colohh/image_bed/raw/master/img/%E4%BA%8B%E4%BB%B6%E5%AF%B9%E8%B1%A1%E7%9A%84%E5%B8%B8%E8%A7%81%E5%B1%9E%E6%80%A7%E5%92%8C%E6%96%B9%E6%B3%95.png)]
3.6.5 阻止事件冒泡
事件对象阻止默认行为
让链接不跳转或让提交按钮不提交
<a href="http://www.baidu.com">百度</a> <script> let a = document.querySelector('a'); a.addEventListener('click',function(e){ e.preventDefault;// 阻止链接跳转 }) </script>
阻止事件冒泡的方式
-
利用事件对象里面的 stopPropagation() 方法
e.stopPropagation()
// 先输出 son 再输出 father 最后是 document let son = document.querySelector('.son'); son.addEventListener('click', function(e) { alert('son'); e.stopPropagation();// 阻止冒泡 后面的 father 和 document 都不会再响应了 }, false); let father = document.querySelector('.father'); father.addEventListener('click', function() { alert('father'); }, false); document.addEventListener('click', function() { alert('document'); })
3.6.6 事件委托(代理、委派)
(1)事件委托的原理
不是给每个子结点单独设置事件监听器,而是将事件监听器设置在其父节点上,然后利用冒泡原理影响设置每个子结点。
(2)事件委托的作用
只操作了一次DOM,提高了程序的性能。
(3)代码实现
当我们点击 li 的时候,因为事件冒泡 所以也会 click 到父节点 ul ,从而触发 alert 事件,而不用给每个 li 单独绑定事件
<ul>
<li>hello</li>
<li>hello</li>
<li>hello</li>
<li>hello</li>
</ul>
<script>
//获取父节点
let ul = document.querySelector('ul');
//给父节点绑定事件
ul.addEventListener('click',function() {
alert('hello')
})
</script>
点击 li 改变 li 的背景颜色:
<ul>
<li>hello</li>
<li>hello</li>
<li>hello</li>
<li>hello</li>
</ul>
<script>
//获取父节点
let ul = document.querySelector('ul');
//给父节点绑定事件
ul.addEventListener('click',function(e) {
// e.target 这个可以得到我们点击的对象
e.target.style.backgroundColor = 'pink';
})
</script>
3.6.7 常用的鼠标事件
(1)鼠标事件
1. 常用的鼠标事件
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5DHQbcz3-1668609195849)(https://gitee.com/colohh/image_bed/raw/master/img/%E5%B8%B8%E8%A7%81%E7%9A%84%E9%BC%A0%E6%A0%87%E4%BA%8B%E4%BB%B6.png)]
- mouseenter 和 mouseover(mouseleave 和 mouseout) 的区别
- mouseenter / mouseleave 鼠标事件
- mouseenter /mouseleave 只会经过自身盒子触发(mouseenter / mouseleave 不会冒泡)
- mouseover / mouseout 鼠标事件
- mouseover / mouseout 鼠标经过自身盒子会触发,经过子盒子还会触发。
- mouseenter / mouseleave 鼠标事件
2. 禁止鼠标右键菜单(了解)
contextmenu 主要控制应该何时显示上下文菜单,主要用于程序员取消默认的上下文菜单(禁用右键菜单)
document.addEventListener('contextmenu',function(e) {
e.preventDefault();
})
3. 禁止选中文字(了解)
document.addEventListener('selectstart',function(e) {
e.preventDefault();
})
(2)鼠标事件对象
event 对象代表事件的状态,跟事件相关的一系列信息的集合。现阶段我们主要用鼠标事件对象 MouseEvent 和键盘事件对象 KeyboardEvent。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jSkXsCB1-1668609195850)(https://gitee.com/colohh/image_bed/raw/master/img/%E9%BC%A0%E6%A0%87%E4%BA%8B%E4%BB%B6%E5%AF%B9%E8%B1%A1.png)]
-
案例 - 跟随鼠标的天使
<head> <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>
3.6.8 常用的键盘事件
(1)常用键盘事件
三个事件同时存在时的顺序: keydown – keypress – keyup
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Bsfwu6WO-1668609195851)(https://gitee.com/colohh/image_bed/raw/master/img/%E5%B8%B8%E7%94%A8%E9%94%AE%E7%9B%98%E4%BA%8B%E4%BB%B6.png)]
(2)键盘事件对象
键盘事件对象(keyboardEvent)中的 keyCode 属性可以得到相应键的 ASCII 码值。
-
利用 keyCode 判断用户按了哪个键
-
keyup 和 keydown 事件不区分字母大小写:按下 a 和 A 得到的都是65
document.addEventListener('keyup',function(e){ console.log(e.keyCode); })
-
keypress 事件区分字母大小写:按下 A 得到65;按 a 得到97
-
4. BOM
4.1 BOM 概述
4.1.1 BOM 简介
- BOM(浏览器对象模型),它提供了独立于内容而与浏览器窗口进行交互的对象,其核心对象是 window。
- BOM 学习的是浏览器窗口交互的一些对象
- BOM 是浏览器厂商在各自浏览器上定义的,兼容性较差
- BOM 由一系列相关的对象组成,并且每个对象都提供了很多方法和属性。
4.1.2 BOM 构成
BOM 比 DOM 更大,它包含 DOM
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-J4ijpbSJ-1668609195852)(https://gitee.com/colohh/image_bed/raw/master/img/BOM%E7%9A%84%E6%9E%84%E6%88%90.png)]
4.2 window 对象的常见事件
- window 对象是浏览器的顶级对象,它具有双重角色
- 它是 JS 访问浏览器窗口的一个接口。
- 他是一个全局对象,定义在全局作用域中的变量、函数都会变成 window 对象的属性和方法
4.2.1 窗口加载事件
当文档内容完全加载完成会触发该事件(包括图像、脚本文件、CSS文件等)
以前 js 部分只能放到 css布局的下面,用这个方法 js 部分就可以放在文件的任意位置
-
window.onload
-
但这种传统的注册事件方式只能写一次,若写了多个,以最后一个为准
window.onload = function(){ ... }
-
window.addEventListener(‘load’, function() {})
-
可以写任意个事件,没有限制
window.addEventListener('load', function() { ... })
-
-
document.addEventlistener(‘DOMContentLoaded’,function() {})
- 仅当 DOM 加载完成(不包含样式表、图片、flash等)时,即触发事件。
- 好处:页面图片过多时,用户访问到onload触发可能需要较长时间,交互效果就不能实现,影响用户体验。此时用 DOMContentLoaded 即可解决。
4.2.2 调整窗口大小事件
只要窗口大小发生像素变化,就会触发这个事件
-
resize
-
使用方式
window.onresize = function() {} window.addEventListener('resize',function() {})
-
常用场景
响应式布局:当我们把浏览器窗口缩小到一定大小时,隐藏某些节点
let div = document.querySelector('div'); windows.addEventLisener('resize',function() { // window.innerWidth 为浏览器窗口宽度 if (window.innerWidth <= 800) { div.style.display = 'none'; } })
-
4.3 定时器
4.3.1 setTimeout() 定时器
setTimeout() 这个调用函数我们也称为回调函数 callback
-
语法规范(window可以省略)
-
定时器到期后调用函数
-
延时时间单位是毫秒,可以省略
-
这个调用函数可以直接写函数,还可以写函数名
window.setTimeout(调用函数,[延迟的毫秒数]);
-
-
停止定时器 clearTimeout()
-
语法规范
window.clearTimeout(timeoutID)
-
实际运用
<button>点击停止计时器</button> <script> let btn = document.querySelector('button'); let timer = setTimeout(function() { console.log('boom!') },5000); btn.addEventListener('click',function() { clearTimeout(timer);// 停止计时器 }) </script>
-
4.3.2 setInterval() 定时器
-
语法规范(window可以省略)
-
反复调用这个函数:每隔这个时间,就去调用一次这个函数
-
间隔的毫秒数默认是 0
-
第一次执行时也有间隔毫秒数,因此刷新页面会有空白
- 解决方式:可以先调用一次这个函数(setInterval()之前),防止刷新后空白
-
这个调用函数可以直接写函数,还可以写函数名
window.setInterval(回调函数,[间隔的毫秒数]);
-
-
停止定时器 clearInterval()
-
语法规范
window.clearInterval(timeoutID)
-
实际运用
<button class="begin">点击开启计时器</button> <button class="stop">点击停止计时器</button> <script> let begin = document.querySelector('.begin'); let stop = document.querySelector('.stop'); let timer = null;// 全局变量 null是一个空对象 begin.addEventListener('click',function() { timer = setInterval(function() { console.log('boom') },1000); }) stop.addEventListener('click',function() { clearInterval(timer);// 停止计时器 }) </script>
-
4.3.3 this指向问题
一般情况下this的最终指向的是那个调用它的对象
-
全局作用域或者普通函数中this指向全局对象window( 注意定时器里面的this指向window)
console.log(this); function fn() { console.log(this); } window.setTimeout(function() { console.log(this); }, 1000);
-
方法调用中谁调用this指向谁
let o = { sayHi: function() { console.log(this); // this指向的是 o 这个对象 } } o.sayHi();
-
构造函数中this指向构造函数的实例
function Fun() { console.log(this); // this 指向的是fun 实例对象 } var fun = new Fun();
4.4 JS 执行机制
JS 是单线程同一个时间只做一件事
4.4.1 同步和异步
为了解决这个问题,利用多核 CPU 的能力,H5 提出 Web Worker 标准,允许 JS脚本创建多个线程。于是,JS中出现了同步和异步。
(1)同步
- 前一个任务结束后再执行下一个任务,程序的执行顺序和任务的排列顺序是一样的。
- 同步任务都在主线程上执行,形成一个执行栈
(2)异步
- 在做这件事的同时,还可以处理其他事情。
- JS 的异步是通过回调函数实现的。异步任务相关回调函数添加到任务队列(消息队列)中
- 一般而言,异步任务有以下三种类型:
- 普通事件:如 click、resize 等
- 资源加载:如 load、error 等
- 定时器:如 setInterval、setTimeout 等
4.4.2 执行机制
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uaw7QT4f-1668609195852)(https://gitee.com/colohh/image_bed/raw/master/img/JS%E6%89%A7%E8%A1%8C%E6%9C%BA%E5%88%B6.png)]
- 先执行执行栈中的同步任务。
- 异步任务(回调函数)放入任务队列中。
- 一旦执行栈中的所有同步任务执行完毕,系统就会按次序读取任务队列中的异步任务,于是被读取的异步任务结束等待状态,进入执行栈,开始执行。
4.5 location 对象
window 对象给我们提供了一个 location 属性用于获取或设置窗体的 URL(网址),并且可以用来解析 URL 。因为这个属性返回的是一个对象,所以我们将这个属性也称为 location 对象
4.5.1 location 对象的属性
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-48w6EhFi-1668609195853)(https://gitee.com/colohh/image_bed/raw/master/img/location%E5%AF%B9%E8%B1%A1%E7%9A%84%E5%B1%9E%E6%80%A7.png)]
(1)location.href
-
可以获取网址或实现跳转
<button>点击</button> <script> let btn = document.querySelector('button'); let div = document.querySelector('div'); btn.addEventListener('click', function() { console.log(location.href);// 获取网址 location.href = 'http://www.itcast.cn'; // 实现跳转 }) </script>
(2)location.search
-
可以返回参数 (详见 Web APIs-第三天-10-获取URL参数)
-
登陆页面 login.html
<body> 登陆页面 <!-- form实现跳转 --> <form action="index.html" method=" get"> 用户名: <input type="text" name="uname"> <input type="submit" value="登录"> </form> </body>
-
主页 index.html
<body> 首页 <div> <i>andy</i> 欢迎光临 </div> <script> let i = document.querySelector('i'); // 通过 location.search 把参数 uname 拿过来 console.log(location.search);// ?uname=andy // 1.先去掉? substr('起始的位置',截取几个字符) let params = location.search.substr(1); // 2.利用 = 把字符串分割为数组 split('='); let arr = params.split('='); // 3.把数据写入div中 i.innerHTML = arr[1]; // console.log(location.href) </script> </body>
-
4.5.2 location 对象的方法
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-heTu4x3V-1668609195853)(https://gitee.com/colohh/image_bed/raw/master/img/location%E5%AF%B9%E8%B1%A1%E7%9A%84%E6%96%B9%E6%B3%95.png)]
(1)location.assign()
-
跳转页面
- location.assign() 是记录浏览历史的,所以可以实现后退功能
<button>按钮</button> <script> let btn = document.querySelector('button'); btn.addEventListener('click',function() { location.assign('https://www.bilibili.com'); }) </script>
(2)location.replace()
- 跳转页面,用法同 assign
- location.replace() 不记录浏览历史,所以不能后退
(3)location.reload()
-
刷新页面
<button>按钮</button> <script> let btn = document.querySelector('button'); btn.addEventListener('click',function() { location.reload(); location.reload(ture);// 强制刷新 }) </script>
4.6 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 = "../H5/index.html"; //手机 }
4.7 history 对象
window 对象给我们提供了一个 history 对象,与浏览器历史记录进行交互。该对象包含用户(在浏览器窗口中)访问过的 URL。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-V1iM3Ivs-1668609195853)(https://gitee.com/colohh/image_bed/raw/master/img/history%E5%AF%B9%E8%B1%A1%E6%96%B9%E6%B3%95.png)]
代码示例:
<body>
<a href="list.html">点击我去往列表页</a>
<button>前进</button>
<script>
let btn = document.querySelector('button');
btn.addEventListener('click',function() {
// history.forward()
// 前进
history.go(1)
})
</script>
</body>
let btn = document.querySelector('button');
btn.addEventListener('click',function() {
location.assign('https://www.bilibili.com');
})
```
(2)location.replace()
- 跳转页面,用法同 assign
- location.replace() 不记录浏览历史,所以不能后退
(3)location.reload()
-
刷新页面
<button>按钮</button> <script> let btn = document.querySelector('button'); btn.addEventListener('click',function() { location.reload(); location.reload(ture);// 强制刷新 }) </script>
4.6 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 = "../H5/index.html"; //手机 }
4.7 history 对象
window 对象给我们提供了一个 history 对象,与浏览器历史记录进行交互。该对象包含用户(在浏览器窗口中)访问过的 URL。
[外链图片转存中…(img-V1iM3Ivs-1668609195853)]
代码示例:
<body>
<a href="list.html">点击我去往列表页</a>
<button>前进</button>
<script>
let btn = document.querySelector('button');
btn.addEventListener('click',function() {
// history.forward()
// 前进
history.go(1)
})
</script>
</body>