JS收官
一、快速掌握BOM对象核心技能
1.DOM, DOCUMENT, BOM, WINDOW 区别
DOM 是为了操作文档出现的 API,document 是其的一个对象;
BOM 是为了操作浏览器出现的 API,window 是其的一个对象。
BOM是浏览器对象模型,DOM是文档对象模型,前者是对浏览器本身进行操作,而后者是对浏览器(可看成容器)内的内容进行操作
归DOM管的:
E区(就是你说的document啦。由web开发人员呕心沥血写出来的一个文件夹,里面有index.html,CSS和JS什么鬼的,部署在服务器上,我们可以通过浏览器的地址栏输入URL然后回车将这个document加载到本地,浏览,右键查看源代码等。
归BOM管的:
A区(浏览器的标签页,地址栏,搜索栏,书签栏,窗口放大还原关闭按钮,菜单栏等等)
B区(浏览器的右键菜单)
C区(document加载时的状态栏,显示http状态码等)
D区(滚动条scroll bar)
2.关于BOM知识的思维导图
3.BOM对象
window 对象,是 JS 的最顶层对象,其他的 BOM 对象都是 window 对象的属性;
document 对象,文档对象;
location 对象,浏览器当前URL信息;
navigator 对象,浏览器本身信息;
screen 对象,客户端屏幕信息;
history 对象,浏览器访问历史信息;
1) window对象:
BOM的核心对象是window,它表示浏览器的一个实例。在浏览器中,window对象有双重角色,它既是通过javascript访问浏览器窗口的一个接口,又是ECMAScript规定的Global对象。
所有 JavaScript 全局对象、函数以及变量均自动成为 window 对象的成员。
全局变量是 window 对象的属性。
全局函数是 window 对象的方法。
window对象常用方法有
弹框类的方法:
alert(‘提示信息’)
confirm(“确认信息”)
prompt(“弹出输入框”)
open(“url地址”,“打开的方式(可以是-self或-black)”,“新窗口的大小”)注:如果url为空,则默认打开一个空白页面,如果打开方式为空,则默认为新窗口方式打开页面。返回值为:返回新打开窗口的window对象
close() 关闭当前的网页。
window.moveTo() - 移动当前窗口
window.resizeTo() - 调整当前窗口的尺寸
定时器,清除定时器。
setTimeout(函数,时间) 只执行一次
setInterval(函数,时间) 无限执行
clearTimeout/clearInterval(定时器名称) 清除定时器
2)location对象
window.location对象:用于获得当前页面的地址 (URL),并把浏览器重定向到新的页面。在编写时可不使用 window 这个前缀。
location.herf = ‘url地址’
hash 返回#号后面的字符串,不包含散列,则返回空字符串。
host 返回服务器名称和端口号
pathname 返回目录和文件名。 /project/test.html
search 返回?号后面的所有值。
port 返回URL中的指定的端口号,如URL中不包含端口号返回空字符串
portocol 返回页面使用的协议。 http:或https:
3)navigator对象
window.navigator 对象包含有关访问者浏览器的信息。在编写时可不使用 window 这个前缀。
navigator.platform:操作系统类型;
navigator.userAgent:浏览器设定的User-Agent字符串。
navigator.appName:浏览器名称;
navigator.appVersion:浏览器版本;
navigator.language:浏览器设置的语言;
userAgent是最常用的属性,用来完成浏览器判断。
4)screen对象
window.screen 对象包含有关用户屏幕的信息。
screen.availWidth 属性返回访问者屏幕的宽度,以像素计,减去界面特性,比如窗口任务栏。
screen.availHeight 属性返回访问者屏幕的高度,以像素计,减去界面特性,比如窗口任务栏。
5) history对象
window.history 对象包含浏览器的历史。为了保护用户隐私,对 JavaScript 访问该对象的方法做出了限制。
history.back() - 加载历史列表中的前一个 URL。返回上一页。
history.forward() - 加载历史列表中的下一个 URL。返回下一页。 go(“参数”) -1表示上一页,1表示下一页。
综合以上,页面跳转的方法有:
二、JavaScript必会常用知识点
1. DOCTYPE 渲染模式,其和最后页面被展示的效果有关系
浏览器请求页面大致经历了哪些过程
1. 发送url,DNS查询,请求IP地址
2. TCP三次握手
3. 服务器响应内容
4. 按照成哥讲的js时间线理解js解析执行的过程就好
5. 渲染页面: DOM树 CSSDOM树,生成RENDER树,布局,渲染
6. TCP四次挥手
如何控制显示页面的浏览器采取什么样的模式来渲染 DOCTYPE
2.Lable标签
var oLabel = document.getElementsByTagName('label')[0];
oLabel.onclick = function () {
console.log(this);
}
var oInput = document.getElementById('demo');
oInput.onclick = function () {
console.log(this);
}
属性特性
特性天生就可以具有的如 id type class value checked 有映射关系 js对象->html标签
属性包含特性 非特性的属性 data cst log times等等 无映射关系 js对象->html标签
setAttribute getAttribute 是属性就能赋值
jq源码 attr prop底层原理就是这个
3.图片预加载
var oImage = new Image();
oImage.src = 'https://ss3.bdstatic.com/70cFv8Sh_Q1YnxGkpoWK1HF6hhy/it/u=2187922730,604631233&fm=27&gp=0.jpg';
oImage.onload = function () {
document.body.appendChild(this);
}
当一个页面的图片很多,或者有图片很大的时候,就可以使用图片预加载的技术来提升用户的体验效果。图片预加载技术核心是用到了Image对象,将图片预先存在Image对象中,当需要展示这张图片的时候,就可以直接从浏览器缓存中获取
三、运动
1.运动原理
Js运动,本质来说,就是让 web 上 DOM 元素动起来。而想要 DOM 动起来,改变其自身的位置属性,比如高宽,左边距,上边距,透明度等。还有一个很重要的前提是,运动的物体必须是绝对定位。
window.onload = function(){
var oBtn = document.getElementById('btn');
oBtn.onclick = function(){
var oDiv = document.getElementById('div1');
//设置定时器
setInterval(function(){
//改变物体位置
oDiv.style.left = oDiv.offsetLeft + 10 + 'px';
},30)
}
}
上述代码,点击btn之后,就能是物体向左运动。可是会一直向右动,不会停止。因此需要创立一个停止的条件。在条件符合的情况下,清楚定时器。其中对于目标点的判断,尤为重要。
window.onload = function(){
var oBtn = document.getElementById('btn');
oBtn.onclick = function(){
var oDiv = document.getElementById('div1');
//设置定时器
var timer = setInterval(function(){
//判断停止条件
if(oDiv.offsetLeft > 300){
clearInterval(timer);
}else{
//改变物体位置
oDiv.style.left = oDiv.offsetLeft + 10 + 'px';
document.title = oDiv.offsetLeft;
}
},30);
}
}
上述代码中,但物体的位置大于300的时候,将停止运动。但是上述代码还有个问题,就是连续点击按钮,物体会运动越来越快。因为每点击一次,就开了一个定时器,累加的定时器。造成运动混乱。
2.运动框架 (滑入滑出,淡入淡出)
window.onload = function(){
var oBtn = document.getElementById('btn');
oBtn.onclick = function(){
startMove();
}
}
var timer = null;
function startMove(){
var oDiv = document.getElementById('div1');
clearInterval(timer);
//设置定时器
timer = setInterval(function(){
//判断停止条件
if(oDiv.offsetLeft > 300){
clearInterval(timer);
}else{
//改变物体位置
oDiv.style.left = oDiv.offsetLeft + 10 + 'px';
document.title = oDiv.offsetLeft;
}
},30);
}
此外,在改变物体位置的时候,那个 “10”则是更改的数量,其实也就是速度。如果更改速度,运动的快慢就能确定。因此,运动框架的原理,基本步骤为:
1.先清除定时器
2.开启定时器,计算速度
3.判断停止条件,执行运动
var timer = null;
function startMove(){
var oDiv = document.getElementById('div1');
clearInterval(timer);
//计算速度
var iSpeed = 10;
//设置定时器
timer = setInterval(function(){
//判断停止条件
if(oDiv.offsetLeft > 300){
clearInterval(timer);
}else{
//改变物体位置
oDiv.style.left = oDiv.offsetLeft + iSpeed + 'px';
document.title = oDiv.offsetLeft;
}
},30);
}
淡入淡出,即改变物体的透明度,由于没有像原生的位置属性那样的offsetLset. 需要一个变量来保存透明度的值,用来和速度加减,最后付给元素的透明度样式。从而实现淡入淡出效果。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>JS运动——淡入淡出</title>
<style>
#div1{ width: 100px; height: 100px; background: green; position: absolute; filter:alpha(opacity:30); opacity: .3;}
</style>
<script>
window.onload = function(){
var oDiv = document.getElementById('div1');
var timer = null;
var alpha = 30;
oDiv.onmouseover = function(){
startMove(10,100);
};
oDiv.onmouseout = function(){
startMove(-10,30);
};
function startMove(speed,iTarget){
var oDiv = document.getElementById('div1');
clearInterval(timer);
timer = setInterval(function(){
if(alpha == iTarget){
clearInterval(timer);
}else{
alpha += speed;
oDiv.style.filter = 'alpha(opacity:' + alpha +')';
oDiv.style.opacity = alpha/100;
}
},30);
}
};
</script>
</head>
<body>
<div id="div1"></div>
</body>
</html>
3.匀速运动:
匀速运动的停止条件:距离足够近
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>匀速运动</title>
<style>
#div1 {width:100px; height:100px; background:red; position:absolute; left:600px; top:50px;}
#div2 {width:1px; height:300px; position:absolute; left:300px; top:0; background:black;}
#div3 {width:1px; height:300px; position:absolute; left:100px; top:0; background:black;}
</style>
<script>
/*
匀速运动的停止条件
距离足够近
*/
window.onload = function(){
var oBtn1 = document.getElementById('btn1');
var oBtn2 = document.getElementById('btn2');
var oDiv = document.getElementById('div1');
var timer = null;
oBtn1.onclick = function(){
startMove(100);
};
oBtn2.onclick = function(){
startMove(300);
};
function startMove(iTarget){
var oDiv = document.getElementById('div1');
clearInterval(timer);
timer = setInterval(function(){
var speed = 0;
if(oDiv.offsetLeft < iTarget ){
speed = 7;
}else{
speed = -7;
}
if(Math.abs(iTarget - oDiv.offsetLeft)<=7){
clearInterval(timer);
oDiv.style.left = iTarget + 'px';
}else{
oDiv.style.left = oDiv.offsetLeft + speed + 'px';
}
},30);
};
};
</script>
</head>
<body>
<!-- <input type="button" value="到100" οnclick="startMove(100)" />
<input type="button" value="到300" οnclick="startMove(300)" /> -->
<input id="btn1" type="button" value="运动到100" />
<input id="btn2" type="button" value="运动到300" />
<div id="div1"></div>
<div id="div2"></div>
<div id="div3"></div>
</body>
</html>
4.缓冲运动
缓冲运动原理就是,改变速度的值。每次累加的速度值变小,就是会是整个物体看起来越来越慢,以至于最后停掉。
window.onload = function(){
var btn = document.getElementsByTagName('input')[0];
btn.onclick = function(){
startMove(300);
}
}
var timer = null;
function startMove(iTarget){
var oDiv = document.getElementById('div1');
clearInterval(timer);
timer = setInterval(function(){
//求出带有变化的速度
var iSpeed = (iTarget - oDiv.offsetLeft) / 8;
if(oDiv.offsetLeft == iTarget){
clearInterval(timer);
}else{
oDiv.style.left = oDiv.offsetLeft + iSpeed + 'px';
}
document.title = oDiv.offsetLeft + '...' + iSpeed;
},30);
}
上述方法可以得到缓冲运动,但是实际运行效果,物体并没有在 300的位置停掉,而是在 293的位置就停掉了。究其原因。因为当物体的速度小于1 的时候。物体位置为293。此时计算的速度是 0.875.通过 oDiv.style.left = oDiv.offsetLeft + iSpeed + ‘px’; 物体的位置为 293.875.可是计算机不能识别小数,将小数省略了。此时的 位置offsetLeft仍然是 293.再计算一次,还是同样的结果。定时器没有关掉,但是物体的位置却再也无法改变,故停留在了 293的位置。解决方案,就是将速度进行向上取整。但是,像上述运动,速度是正的,可是,当速度是负的时候,就同样会有相同的结果,因此需要在速度为负的时候,向下取整。
function startMove(iTarget){
var oDiv = document.getElementById('div1');
clearInterval(timer);
timer = setInterval(function(){
var iSpeed = (iTarget - oDiv.offsetLeft) / 8;
//对正的速度向上取整,负的速度向下取整
iSpeed = iSpeed > 0 ? Math.ceil(iSpeed) : Math.floor(iSpeed);
if(oDiv.offsetLeft == iTarget){
clearInterval(timer);
}else{
oDiv.style.left = oDiv.offsetLeft + iSpeed + 'px';
}
document.title = oDiv.offsetLeft + '...' + iSpeed;
},30);
}
1、当前值离目标值越近,速度越慢
当前值离目标值越远,速度越快
speed = (目标值-当前值)/10
2、与目标点相差一点,需要进行判断
目标值>当前值,需要对速度向上取整,即speed = Math.ceil(speed)
目标值<当前值,需要对速度向下取整,即speed = Math.floor(speed)
3、如果当前值=目标值,清除动画
<html>
<head>
<meta charset="utf-8" />
<title>
缓冲运动
</title>
<link rel="stylesheet" type="text/css" href="css/index.css"/>
<script src="js/index.js"></script>
<!--<base target="_blank" />-->
<style>
.wrapper{
width: 400px;
height: 80px;
background: orange;
position: absolute;
left: 0px;
top: 200px;
}
.wrapper span{
width: 50px;
height: 80px;
background: red;
position: absolute;
right: -50px;
top: 0px;
}
</style>
</head>
<body>
<div class="wrapper">
<span></span>
</div>
<div></div>
<!-- <button id='btn'>运动</button> -->
<span></span>
<script>
var timer = null;
var oDiv = document.getElementsByClassName('wrapper')[0];
oDiv.onmouseenter = function(){
starMove(this,0)
}
oDiv.onmouseleave = function(){
starMove(this,-400)
}
function starMove(dom,target){
clearTimeout(timer);
var iSpeed=null;
timer=setInterval(function(){
iSpeed=(target-oDiv.offsetLeft) /7;
iSpeed=iSpeed > 0 ? Math.ceil(iSpeed):Math.floor(iSpeed);
oDiv.style.left=oDiv.offsetLeft+iSpeed+'px';
},30);
}
</script>
</body>
</html>
5.多物体运动
下一步,就是处理多物体运动,运动函数里面每次都要选取一个元素加事件。如果需要对多个物体进行同样的运动, 需要将运动对象作为参数传进来。
window.onload = function(){
var aDiv = document.getElementsByTagName('div');
for(var i=0;i<aDiv.length;i++){
aDiv[i].onmouseover = function(){
startMove(this,300);
}
aDiv[i].onmouseout = function(){
startMove(this,100);
}
}
}
function startMove(obj,iTarget){
//将定时器,变成物体的属性,类似给物体添加索引
clearInterval(obj.timer);
obj.timer = setInterval(function(){
var iSpeed = (iTarget - obj.offsetWidth) / 8;
iSpeed = iSpeed > 0 ? Math.ceil(iSpeed) : Math.floor(iSpeed);
if(obj.offsetWidth == iTarget){
clearInterval(obj.timer);
}else{
obj.style.width = obj.offsetWidth + iSpeed + 'px';
}
},30)
}
通过循环物体,将物体的 this传给运动函数,使得多物体可以运动。但是这样有一个弊端,即当滑入第一个运动的时候,开启了定时器。如果此时,滑入另外一个物体,将会清理上一个定时器。这就造成了,上一次运动,很有可能还没完成结束,定时器就没关闭了。解决的方法,每个运动的物体,都能开了一个属于自己的定时器。因此,把定时器当成物体的属性。清理的时候也就是清理自己的定时器。
6.拖拽实例
1.模拟重力场,拖拽实例
每次拖动时,浏览器监听是有间隔的。
<!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 {
position: absolute;
left: 0px;
top: 0px;
background: orange;
width: 100px;
height: 100px;
}
</style>
</head>
<body>
<div id='demo'></div>
<script>
var oDiv = document.getElementById('demo');
var lastX = 0;
var lastY = 0;
var iSpeedX = 0;
var iSpeedY = 0;
oDiv.onmousedown = function (e) {
clearInterval(this.timer);//清理当前定时器,防止冲突
var event = event || e;
var disX = event.clientX - this.offsetLeft; //鼠标点击的位置-离左边边界的距离
var disY = event.clientY - this.offsetTop;
var self = this;
document.onmousemove = function (e) {
var event = event || e;
var newLeft = event.clientX - disX;
var newTop = event.clientY - disY;
iSpeedX = newLeft - lastX;//设定横向与纵向速度,当前的横向距离-上一个横向距离
iSpeedY = newTop - lastY;
lastX = newLeft; //值的更新(做为上一个点)
lastY = newTop;
// var oSpan = document.createElement('span');
// oSpan.style.position = 'absolute';
// oSpan.style.left = newLeft + 'px';
// oSpan.style.top = newTop + 'px';
// oSpan.style.width = '5px';
// oSpan.style.height = '5px';
// oSpan.style.backgroundColor = 'black';
// document.body.appendChild(oSpan);
self.style.left = newLeft + 'px';
self.style.top = newTop + 'px';
}
document.onmouseup = function () { //松开鼠标取消事件,同时调用 startMove
document.onmouseup = null;
document.onmousemove = null;
startMove(self, iSpeedX, iSpeedY);
}
}
function startMove (dom, iSpeedX, iSpeedY) {
clearInterval(dom.timer);
var g = 3;
dom.timer = setInterval(function () {
iSpeedY += g;//设置g,更新iSpeedY的值
var newTop = dom.offsetTop + iSpeedY;
var newLeft = dom.offsetLeft + iSpeedX;
if (newTop >= document.documentElement.clientHeight - dom.clientHeight) {
//当前界面的高度-块的高度
iSpeedY *= -1;
iSpeedY *= 0.8;//能量损失
iSpeedX *= 0.8;
newTop = document.documentElement.clientHeight - dom.clientHeight;//不出现滚动条
}
if (newTop <= 0) {
iSpeedY *= -1;
iSpeedY *= 0.8;
iSpeedX *= 0.8;
newTop = 0;
}
if (newLeft >= document.documentElement.clientWidth - dom.clientWidth) {
iSpeedX *= -1;
iSpeedY *= 0.8;
iSpeedX *= 0.8;
newLeft = document.documentElement.clientWidth - dom.clientWidth;
}
if (newLeft <= 0) {
iSpeedX *= -1;
iSpeedY *= 0.8;
iSpeedX *= 0.8;
newLeft = 0;
}
if (Math.abs(iSpeedX) < 1) {
iSpeedX = 0;
}
if (Math.abs(iSpeedY) < 1) {
iSpeedY = 0;
}
if (iSpeedX == 0 && iSpeedY == 0 && newTop == document.documentElement.clientHeight - dom.clientHeight) {
clearInterval(dom.timer);
console.log('over')
}else {
dom.style.top = newTop + 'px';
dom.style.left = newLeft + 'px';
}
}, 30);
}
</script>
</body>
</html>
7.数组方法(数组迭代)
1.Array.forEach()
forEach() 方法为每个数组元素调用一次函数(回调函数)。
该函数接受 3 个参数:
项目值
项目索引
数组本身
<!DOCTYPE html>
<html>
<body>
<h1>JavaScript Array.forEach()</h1>
<p>为每个元素调用一次函数。</p>
<p id="demo"></p>
<script>
var txt = "";
var numbers = [45, 4, 9, 16, 25];
numbers.forEach(myFunction);
document.getElementById("demo").innerHTML = txt;
function myFunction(value) {
txt = txt + value + "<br>";
}
</script>
</body>
</html>
2.Array.filter()
filter() 方法创建一个包含通过测试的数组元素的新数组。
函数接受 3 个参数:
项目值
项目索引
数组本身
例子中,回调函数不使用 index 和 array 参数,因此可以省略它们:
对数组过滤的作用,基于遍历之上
filter执行完后,会返回一个新的数组【】
return可以直接判断true/false,true保留,false过滤
<!DOCTYPE html>
<html>
<body>
<h1>JavaScript Array.filter()</h1>
<p>使用通过测试的所有数组元素创建一个新数组。</p>
<p id="demo"></p>
<script>
var numbers = [45, 4, 9, 16, 25];
var over18 = numbers.filter(myFunction);
document.getElementById("demo").innerHTML = over18;
function myFunction(value, index, array) {
return value > 18;
}
</script>
</body>
</html>
3.Array.map()
map() 方法通过对每个数组元素执行函数来创建新数组。
map() 方法不会对没有值的数组元素执行函数。
map() 方法不会更改原始数组。
该函数有 3 个参数:
项目值
项目索引
数组本身
当回调函数仅使用 value 参数时,可以省略索引和数组参数:
var numbers1 = [45, 4, 9, 16, 25];
var numbers2 = numbers1.map(myFunction);
function myFunction(value) {
return value * 2;
}
每次执行完返回的值,就会改变数组的值
4.Array.every()
every() 方法检查所有数组值是否通过测试。
此函数接受 3 个参数:
项目值
项目索引
数组本身
如果回调函数仅使用第一个参数(值)时,可以省略其他参数:
<!DOCTYPE html>
<html>
<body>
<h1>JavaScript Array.every()</h1>
<p>every() 方法检查所有数组值是否通过测试。</p>
<p id="demo"></p>
<script>
var numbers = [45, 4, 9, 16, 25];
var allOver18 = numbers.every(myFunction);
document.getElementById("demo").innerHTML = "所有大于 18 是:" + allOver18;
function myFunction(value) {
return value > 18;
}
</script>
</body>
</html>
5.Array.some()
some() 方法检查某些数组值是否通过了测试。
此函数接受 3 个参数:
项目值
项目索引
数组本身
<!DOCTYPE html>
<html>
<body>
<h1>JavaScript Array.some()</h1>
<p>some() 方法检查某些数组值是否通过了测试。</p>
<p id="demo"></p>
<script>
var numbers = [45, 4, 9, 16, 25];
var someOver18 = numbers.some(myFunction);
document.getElementById("demo").innerHTML = "某些值大于 18 是:" + someOver18;
function myFunction(value, index, array) {
return value > 18;
}
</script>
</body>
</html>
6.Array.reduce()
reduce() 方法在每个数组元素上运行函数,以生成(减少它)单个值。
reduce() 方法在数组中从左到右工作。另请参阅 reduceRight()。
reduce() 方法不会减少原始数组。
此函数接受 4 个参数:
总数(初始值/先前返回的值)
项目值
项目索引
数组本身
reduce() 方法能够接受一个初始值:
var sum = numbers.reduce(myFunction, 100);
<!DOCTYPE html>
<html>
<body>
<h1>JavaScript Array.reduce()</h1>
<p>此例确定数组中所有数字的总和:</p>
<p id="demo"></p>
<script>
var numbers = [45, 4, 9, 16, 25];
var sum = numbers.reduce(myFunction, 100);
document.getElementById("demo").innerHTML = "总和是:" + sum;
function myFunction(total, value) {
return total + value;
}
</script>
</body>
</html>
7.Array.indexOf()
indexOf() 方法在数组中搜索元素值并返回其位置。
注:第一个项目的位置是 0,第二个项目的位置是 1,以此类推。
array.indexOf(item, start)
item 必需。要检索的项目。
start 可选。从哪里开始搜索。负值将从结尾开始的给定位置开始,并搜索到结尾。
如果未找到项目,Array.indexOf() 返回 -1。
如果项目多次出现,则返回第一次出现的位置。
<!DOCTYPE html>
<html>
<body>
<h1>JavaScript Array.indexOf()</h1>
<p id="demo"></p>
<script>
var fruits = ["Apple", "Orange", "Apple", "Mango"];
var a = fruits.indexOf("Apple");
document.getElementById("demo").innerHTML = "Apple 被找到的位置是:" + (a + 1);
</script>
</body>
</html>
总结
提示:这里对文章进行总结: