灵魂拷问:
浏览器能干什么?
我能让浏览器干什么?
BOM
BOM概述
浏览器对象模型,核心对象是window
BOM缺乏标准,兼容性比较的差,我们学习兼容性较好的一部分
DOM 是W3C标准规范,BOM是各自浏览器厂商定义的。
window
- document
- location
- navigation
- screen
- hsitory
windos是js访问浏览器窗口的一个接口,全局对象。
定义在全局作用域的变量和方法,自动变成window对象的属性和方法。只不过在调用的时候会省略window
js中不要用name命名,因为window中有个属性叫name。
常见的window事件
window.onload 图片,css等全部加载完才触发
document.DOMContentLoaded (DOM加载完就触发,不包括css,flash,图片等)
window.onresize 多用来处理响应式的布局 window.innerWidth 当前屏幕的宽度
定时器
window对象提供了两个定时器
window.setTimeout
setTimeout(fun,[延迟的毫秒数]); 定时炸弹 window可以省略
延迟多少毫秒后调用fun函数。
注意:
- 调用的时候window可以省略
- 延迟时间是毫秒,可以省略,省略的话默认是0,就是立刻执行
- 调用函数可以直接写函数,也可以写函数名,还有一个写法‘函数名()’,但是不常用。
- 页面中可能有很多定时器,我们经常给定时器加标识符(名字)
var time1=setTimeOut( )
var time2=setTimeOut( )
回调函数callback
回调函数不是按顺序执行,而是当满足一定条件才触发。
停止setTimeout()定时器。(拆除炸弹)
clearTimeout(定时器名字);
window.setInterval()
setInterval(回调函数,延时时间)
死循环,一直执行。
window.clearInterval(time1) 清除定时器
技巧: 设置公共变量来传参,并初始化成一个null对象
<body>
<button class="start">开始定时器</button>
<button class="stop">停止定时器</button>
<script>
var btnStart = document.querySelector('.start');
var btnStop = document.querySelector('.stop');
var timer=null;
btnStart.addEventListener('click',function(){
timer= setInterval(function(){
console.log('nihao!');
},1000);
});
btnStop.addEventListener('click',function(){
clearInterval(timer);
});
</script>
</body>
this指向问题
一般情况下 ,this指向最终调用它的对象
1、全局作用域下,this指向window对象
定时器中,this指向window
2、方法调用中,谁调用就指向谁
3、构造函数 ,指向新对象
JS执行机制
原先,js是单线程,同一时间只能做一件事
现在 html5允许js创建多个线程
同步和异步
同步任务都在主线程执行,形成一个执行栈
异步任务通过回调函数实现。
一般来说,异步任务有三种类型:
1、普通事件 click resize等
2、资源加载 load error等
3、定时器,包括setInterval,setTimeout等
异步进程处理原理:
- 主线程执行栈
- 异步任务调度
- 异步任务队列
主线程优先执行同步任务, 对于鼠标点击事件,定时器等异步任务会 由异步任务调度器检测,一旦满足执行条件,会将对应的时间处理函数放入异步任务队列,主线程一旦空闲就会读取异步任务队列中的任务来执行。 也就是说,同一时间内,只有一个线程在执行。
事件循环: 主线程不断的重复获得任务,执行任务,这种机制就叫事件循环
location对象
URL: protocol://host[:port]/path/[?query]#fragment
protocol: 通讯协议
host:主机(域名)
port: 端口号
path: 路径由零或多个/符号隔开的字符串,一般用来表示主机上的一个目录或文件地址
query:参数,以键值对的形式,通过&符号分隔开来
fragment: 判断 #后面内容常见于链接锚点
location常用属性:
href url地址,可读可写
search ?后面的参数
host 主机
location.assign(‘http://www.baidu.com’) 跳转页面,可以后退
location.replace(‘http://www.baidu.com’) 不记录历史,不可以后退
location.reload() 如果参数为true,为强制刷新。 相当于ctrl+f5
navigator
包含了浏览器的相关信息
useragent
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=""; //电脑
}
history
history.forward() 前进
history.back() 后退
history.go(1) 前进一步 -1 后退一步
PC端网页特效
offset
获取元素距离定位父元素的位置
获取元素自身的大小
注意: 返回的数字不带单位
element.offsetParent 返回带有定位的父元素,如果没有,返回body
element.offsetTop 距离父元素上沿的像素
element.offsetLeft 距离父元素左沿的像素
如果没有父亲或者附近没有定位,则返回相对body的值。
element.offsetWidth()
element.offsetHeight()
offset | style | |
---|---|---|
1 | 可以得到任意样式表中的样式值 | 只能得到行内样式表中的值 |
2 | 得到的是数字型的,没有单位 | 字符串,有单位 |
3 | offsetwidth 包含padding+border+width | 只是width |
4 | 只读属性 | 可读可写 |
5 | 所以,获取元素大小位置,用offset更合适 | 改变大小,用style更合适 |
显示鼠标在盒子内的位置:
var box=document.querySelector('.box');
left = box.offsetLeft;
top1 = box.offsetTop;
box.addEventListener('mousemove',function(e){
console.log(e.pageX-left,e.pageY-top1);
})
拖动模态框案例:
重点:
要给盒子注册三个事件
1、mousedown : 获取鼠标在盒子内的坐标值x=e.pageX-element.offsetX y=e.pageY-element.offsetY
2、mousemove: 设置盒子的top和left值 element.style.top = e.pageX-x+‘px’
注意两点:
- style 像素值要加单位
- mousemove事件要在mousedown事件里面绑定
3、mouseup
解绑鼠标移动事件
var login =document.querySelector('.login');
function doShow(){
login.style.display ='block';
}
function doClose(){
login.style.display ='none';
}
var x,y;
function move(e){
login.style.top=(e.pageY-y ) +'px';
login.style.left = e.pageX-x+'px';
}
login.addEventListener('mousedown',function(e){
x=e.pageX-this.offsetLeft;
y = e.pageY-this.offsetTop;
login.addEventListener('mousemove',move);
})
login.addEventListener('mouseup',function(){
login.removeEventListener('mousemove',move);
})
client
element.clientTop 上边框的大小
element.clientLeft 左边框的大小
element.clientWidth 自身padding,内容区的宽度
element.clientHeight 自身padding,内容区的高度
(跟offsetWidth的区别就是不包含边框)
立即执行函数
(function(){})(参数);
(函数声明)(调用参数);
也可以这样写:
(function (){}())
(函数声明())
立即执行函数最大的作用是独立创建了一个作用域,里面所有的变量都时私有变量,避免命名冲突问题。
淘宝flexible.js源码分析
pageshow
比load触发的机会更多,不管是load还是前进后退都会触发。
scroll
element.scrollTop 返回被卷去的上侧距离,不带单位(内容上沿到上边框下沿的距离)
element.scrollLeft 返回被卷去的左侧距离,返回数值不带单位
element.scrollWidth 返回自身实际的宽度,不含边框,包括超出盒子的部分
element.scrollHeight 返回自身实际的高度,不含边框,返回数值不带单位
onscroll事件,拖动滚动条就会触发这个事件。
页面被卷去的头部:(整个页面,如果是元素,请用上面介绍的scrolltop)
window.pageYOffset
window.pageXOffset
三大系列总结
1 都可以返回元素大小
offsetwidth : 包含边框
clientwidth: 不包含边框,只有content和padding
corllwidth: 实际内容的大小,不含边框。
他们的主要用法:
1 offset系列经常用于获得元素位置
2、client系列经常用户获取元素大小
3、scroll经常用于获取滚动距离 scrolltop scrollleft
4 、注意页面滚动的距离通过window.pageXoffset获得。
mouseenter和mouseover事件的区别:
mouseover:
进入自身和进入自身内部的子元素都会触发,符合冒泡规则
mouseenter:
进入自身只触发一次,不会触发冒泡规则
与之对应的是mouseleave
动画实现的原理
通过setInternal不断调整元素位置
元素要加定位
注意:
1 先获取元素当前位置 offsettop offsetleft
2、 让盒子在当前位置加上1个移动距离
3、利用定时器不断重复这个操作
4、加一个结束定时器的条件
5、注意此元素需要添加定位
function animate(obj,target){
var timer=setInterval(function(){
if(obj.offsetLeft>=target){
clearInterval(timer);
}
obj.style.left = obj.offsetLeft+5+'px';
},30)
}
var div = document.querySelector("div");
animate(div,500);
进一步优化: 给不同的元素开启不同的定时器:
var timer 改成 obj.timerv
function animate(obj,target){
clearInterval(obj.timer); //防止多次执行出现多个定时器
obj.timer=setInterval(function(){
if(obj.offsetLeft>=target){
clearInterval(timer);
}
obj.style.left = obj.offsetLeft+5+'px';
},30)
}
var div = document.querySelector("div");
animate(div,500);
缓动动画原理:
盒子每次移动的距离慢慢变小
核心算法: 每次移动的距离=(目标距离-当前位置)/10
轮播图
略
手机端网页特效
触屏事件touch
代替鼠标事件:
touchstart 相当于 mousedown
touchmove 相当于 mousemove
touchend 相当于 mouseup
触摸事件: TouchEvent
触摸列表:
touches 正在触摸屏幕的所有手指的一个列表
gargetTouches 正在触摸当前DOM元素上的手指的一个列表
changeTouches 手指状态发生了改变的列表,从无到有,从有到无变化
因为平时我们都是给元素注册触摸事件,所以重点记住targetTouches
滚动到某个地方显示返回顶部
<!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>
body {
height: 3000px;
}
.goback {
position:fixed;
right: 30px;
bottom:30px;
display: none;
width: 50px;
height: 50px;
background-color: pink;
}
</style>
</head>
<body>
<div class="goback">go top</div>
<script>
var goback = document.querySelector(".goback");
goback.addEventListener('click',function(){
window.scroll(0,0);
})
window.addEventListener('scroll',function(){
if (window.pageYOffset>1000){
goback.style.display='block';
}else{
goback.style.display='none';
}
})
</script>
</body>
</html>
click 延时解决方案
为了区分两个手指缩放屏幕,click事件都有300ms的延时。
如果想取消这个延时,用户点击立刻响应,有下面几种处理方式。
1 让用户禁止缩放
2 自己编写函数处理
3 fastclick插件
Swiper 轮播图
中文官网:https://www.swiper.com.cn
1 引入插件相关文件
2 按照规定语法使用
其他移动端常见插件
superslide http://www.superslide2.com
iscroll: https://github.com/cubig/iscroll
移动端视频插件 zy.media.js
因为各大浏览器实现的控制界面不一样,所以为了在各大浏览器取得一致的显示效果,可以采用视频插件。
移动端常用开发框架
框架: 大而全,一整套解决方案
插件: 小而专,某个功能的解决方案
bootstrap vue angular react
本地存储(WEB STORAGE)
本地存储特性:
- 数据存储在浏览器中
- 设置读取方便,页面刷新不会丢失数据
- 容量较大,sessionStorage越5M,localStorage越20M
- 只能存储字符串,可以将对象JSON.stringify()编码后存储
window.sessionStorage
生命周期为关闭浏览器窗口
window.localStorage
1 声明周期永久生效,除非手动删除,否则关闭页面也会存在
2 可以多窗口共享(同一浏览器)
相关API
<script>
function saveData(){
const person = {name:"张三",age:18}
localStorage.setItem('p',JSON.stringify(person));
}
function getData(){
person = localStorage.getItem('p');
person = JSON.parse(person)
alert(person.name)
}
function delData(){
localStorage.removeItem('p');
}
function clearData(){
localStorage.clear();
}
</script>
注意:
1、LocalStorage存储的内容,需要手动清除才能消失(调用api清除,或者手动清除缓存)
2、getItem(xxx)如果xxx对应的value获取不到,返回null
3、JSON.parse(null)的结果依然是null
4、只能保存字符串,保存数据的时候会自动调用对象的tostring方法