BOM基础

160 阅读8分钟

BOM的概念和window对象

BOM(Browser object Model)是指浏览器对象模型,浏览器对象模型提供了独立于内容的、可以与浏览器窗口进行互动的对象结构。
BOM由多个对象组成,其中代表浏览器窗口的Window对象是BOM的顶层对象,其他对象都是该对象的子对象。
我们在浏览器中的一些操作都可以使用BOM的方式进行编程处理,比如:刷新浏览器、后退、前进、在浏览器中输入URL等。
window对象:
window是浏览器的顶级象,当调用window下的属性和方法时,可以省略window。
注意:window下两个特殊的属性window.name(固定字符串类型)、window.top(只读)。所以不要去定义全局变量name和top,可以定义局部变量name和top。

<script>
  // window 对象是 BOM 中的一个顶层对象,其他的对象都是 window 的子对象。
  // document 对象就是 window 的一个子对象
  // console.dir(window.document);
  // 输出 window 对象
  console.dir(window);
  // window 对象在调用属性和方法时,可以省略 window 不写
  // alert(1);
  // window.alert(2);
  // 在全局作用域定义的全局变量,都是 window 的一个属性
  var age = 18;
  console.log(window.age);
  // window 中 的特殊属性 name,如果定义新的变量,
  // 只会在原来的 name 属性上进行赋值,并且只能是字符串格式的值
  // 所以最好不要去定义全局变量name
  // var name = 123;
  // console.log(window.name);
  // top 属性 在 window 中,属性值指向的就是顶层对象 window,
  // 这个属性是只读的,不能后期更改。
  // var top = 23;
  // console.dir(window.top);
</script>

对话框

  • alert()警示框
  • prompt()提示框
  • confirm()确认或者取消对话框 因为在不同浏览器中有兼容问题,所以一般对话框都是我们自己设计的,自带对话框一般只用于测试。
// 警示框
btn1.onclick = function () {
  alert("hello");
};
// 提示框
btn2.onclick = function () {
  var num = prompt("请输入一个数字",12);
  console.log(num);
};
// 让用户进行确认或者取消选择的对话框
// confirm 方法有返回值,根据按钮点击情况,如果点击确定 返回 true,
// 如果点击取消 返回 false
btn3.onclick = function () {
  var isSure = confirm("请问,您确定要删除这条数据吗?");
  console.log(isSure);
};

onload加载事件

我们可以给window对象或者<img>等元素添加on|oad加载事件,表示只有绑定事件的元素加载完毕才能触发事件,才能执行事件函数。
其中window对象加载完毕:指的是所有HTML结构加载完,并且外部引入资源(js、css、img、视频)也加载完毕。

<div id="box">
  <img src="images/lunbo/01.jpg" alt="">
  <img src="images/lunbo/02.jpg" alt="">
  <img src="images/lunbo/03.jpg" alt="">
  <img src="images/lunbo/04.jpg" alt="">
  <img src="images/lunbo/05.jpg" alt="">
</div>
<script>
  var box = document.getElementById("box");
  var pics = document.getElementsByTagName("img");
  // Chrome 浏览器渲染加载的机制,由于图片加载时间过长,避免等待,
  // 图片在加载过程中,会先执行后面的 js 代码
  // 后续需要使用到 图片的宽度或高度等尺寸,在 js 中可能获取不到
  console.log(box.clientHeight);//输出 0 
  // 图片的加载事件,只要图片加载完毕渲染成功后,就能够立即执行事件函数
  pics[0].onload = function () {
    // 在这里已经保证图片加载成功
    console.log(box.clientHeight);
  };
  
  // 计数器
  var sum = 0;
  for (var i = 0 ; i < pics.length ; i++) {
    pics[i].onload = function () {
      sum++;
      // 判断这一次是否加载所有图片完毕
      if (sum >= pics.length) {
        console.log(box.clientHeight);
      }
    };
  }
  window.onload = function () {
    console.log(box.clientHeight);
  };
</script>
<script>
  // window.onload 事件,一个页面只能使用一次
  window.onload = function () {
    // 事件被触发时,页面所有内容都已经加载完毕,获取元素不会出现错误
    var box = document.getElementById("box");
    var pics = document.getElementsByTagName("img");
    console.log(box.clientHeight);
  };
</script>

延时器

延时器是window对象的一个方法,类似于定时炸弹
语法:window.setTimeout(func,time);
第一个参数:延时执行的函数,可以是匿名函数定义,或者是一个函数名的引用,注意不要 加()。
第二个参数:延时的时间,以亳秒计数,1000亳秒等于1秒。
功能:异步,在指定的时间后,延迟执行一个函数。

// 延时器
// 异步语句
// 延时器为了保证后期能够被清除,需要定义赋值给一个变量
var timeout = window.setTimeout(function () {
  console.log("boom");
},2000);
// 同步语句
console.log(1);
console.log(2);
console.log(3);
console.log(4);
// 清除延时器
window.clearTimeout(timeout);

函数节流操作

函数节流操作

定时器

定时器是window对象的一个方法,相当于定时闹钟,每隔固定的时间响一次
语法:window.setInterval(func,interval)
第一个参数:每次执行的函数,可以是匿名函数定义,或者是一个函数名的引用,注意不要 加()。
第二个参数:时间间隔,以毫秒计数,1000亳秒等于1秒。
功能:每隔一个指定的时间,周期性的执行一个函数。

var i = 1;
// 定时器也是异步语句
// 开启定时器:每隔 0.5 秒输出一次 i,并且让 i 每次自加
// 程序执行到定时器代码部分就相当于开启了一个定时器,不需要进行其他的打开操作
// 第一次执行函数时是在第一个时间间隔之后
// window.setInterval(function () {
//   console.log(i++);
// },500);
// 要想清除定时器,在定义的时候必须存到一个变量中
var timer = setInterval(function () {
  console.log(i++);
},500);
// 清除定时器
window.clearInterval(timer);

简单运动

简单运动:是一种视觉暂留效果,只要元素变化过程时间够短,给人眼造成的效果就是一个 运动的效果,人眼的视觉残留的时间0.1一0.4秒之间。
制作方法:通过定时器,实现每隔一个极短的时间(50一100毫秒左右),执行函数,函数 内部让运动的属性值发生变化。

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    * {
      margin: 0;
      padding: 0;
    }
    .box {
      position: absolute;
      top: 100px;
      left: 0;
      width: 100px;
      height: 100px;
      background-color: skyblue;
    }
  </style>
</head>
<body>
  <input type="button" value="开始" id="start">
  <div class="box" id="box"></div>
  <script>
    // 简单运动
    // 获取元素
    var start = document.getElementById("start");
    var box = document.getElementById("box");
    // 点击开始按钮,让 box 向右运动
    // 全局变量存储 left 的属性值,会每次发生变化
    // 信号量,初始值必须与属性初始值保持一致
    var nowLeft = 0;
    // 定时器,制作运动过程
    start.onclick = function () {
      setInterval(function () {
        // 信号量进行自加
        nowLeft += 5;
        // 将最新的 nowLeft 的值赋值给元素的 css 属性
        box.style.left = nowLeft + "px";
      },100);
    };
  </script>
</body>
</html>

清除定时器的问题

  • 问题一: 将定时器的开始和停止过程书写在不同的事件函数内部,容易出现用户错误点击情况。
    1、多次点击开始,会生成多个定时器,以上面的简单运动为例,会造成加速;
    2、多次点击开始,不能够再停止。因为生成了多个定时器,清除定时器时只是清除了其中一个,其他定时器并没有清除。

解决方法:设表先关。每次开启新的相同定时器之前都要清除一次前面的定时器。

  • 问题二: 需求:要求元素走到指定位置停止,例如让元素停止在500p×的位置
    问题:如果步长设置的不合理,停止的位置可能不是正好在500px处。

解决方法:拉终停表。在定时器内部每次都要判断是否走到了终点,要不要停止定时器。如果走郅或超过了终点,强行拉到终点,并停止定时器。

  • 问题三: 需求:在规定时间内让元素走到规定的结束位置,时间间隔可以更改。
    例如:让元素在2秒钟内,left属性从0走到500px。

解决方法:步标整除。 总距离=步长*次数; 时间间隔自定义,总时长固定; 求出总次数=总时间/时间间隔; 定义计数器变量,每执行一次定时器函数增加计数1,直到执行达到总次数,停止定时器。

多属性运动

由于多属性运动耦合属性太多,我们需要封装一个函数来批量处理这些属性。

封装动画函数

可以将以下函数,封装到js文件中,方便进行调用

// 多属性运动
// 共同点:总时间、时间间隔是相同的,自定义
// 不同的:起始位置(通过程序方法自动获取当前页面最终显示效果)和结束位置(自定义指定的)

// 函数参数
// 参数1:元素对象,它要进行运动
// 参数2:结束位置,以对象数据方式传递
// 参数3:总时间
// 自定义动画函数
function animate(ele,end,time) {
  // 已知结束位置,总时间,时间间隔 50,缺少起始位置
  // 起始位置要根据结束位置提供的属性进行获取
  // 起始位置的对象,需要先定义一个空对象
  var now = {};
  // start.left = 100;
  // end 对象遍历,获取属性名
  for (var k in end) {
    now[k] = parseFloat(window.getComputedStyle(ele)[k]);
  }
  // console.log(start);
  // 自定义时间间隔
  var interval = 50;
  // 计算总次数
  var maxCount = time / interval;
  // 次数累加器
  var count = 0;
  // 对象中的每个属性都有自己的步长,也可以放到一个步长对象中
  var step = {};
  // 遍历结束对象,计算每个属性的步长
  for (var k in end) {
    step[k] = (end[k] - now[k]) / maxCount;
  }
  // console.log(step);
  // ====================准备工作结束,开启定时器=========================
  var timer;
  timer = setInterval(function () {
    // 让每个属性发生变化,赋值给 now 对象中的每一项
    for (var k in end) {
      now[k] += step[k];
    }
    // 累计运动次数
    count++;
    // 判断定时器是否结束
    if (count >= maxCount) {
      // 拉终停表
      for (var k in end) {
        now[k] = end[k];
      }
      clearInterval(timer);
    }
    // 赋值给对应元素对象属性
    for (var k in now) {
      // 判断如果是 不透明度属性,不要加px单位
      if (k === "opacity") {
        ele.style[k] = now[k];
      } else {
        ele.style[k] = now[k] + "px";
      }
    }

  },interval);
}
// 调用函数
start.onclick = function () {
  animate(box,{left: 400,width: 300},2000);
};

无缝滚动轮播图

无缝滚动轮播图

完整切换轮播图

完整切换轮播图

返回顶部效果

// 获取页面卷动的距离
// document.body.scrollTop
// document.documentElement.scrollTop
// 获取元素
var header = my$("top");
var backtop = my$("totop");
// 1.在页面往下卷动到一定距离后,让 header 高度变低,让 返回顶部按钮出现
// 添加页面滚动事件
window.onscroll = function () {
  // 判断卷动走的距离,如果超过 10 px,就让 header 变低,让 返回顶部按钮出现
  if (document.documentElement.scrollTop > 10) {
    header.className = "header fixed";
    backtop.style.display = "block";
  } else {
    header.className = "header";
    backtop.style.display = "none";
  }

  // console.log(document.documentElement.scrollTop);
};
// 变量存储定时器
var timer;
// 2.点击返回顶部,让页面以动画的方式跳转到页面顶部
backtop.onclick = function () {
  // 终点
  var target = 0;
  // 起始点
  var current = document.documentElement.scrollTop;
  // 步长
  var step = 30;
  timer = setInterval(function () {
    // 获取当前卷动的值,每次递减一个步长
    current -= step;
    // 停止定时器
    if (current <= target) {
      current = target;
      clearInterval(timer);
    }
    // 重新赋值
    document.documentElement.scrollTop = current;
  },10);
};

location对象

location对象是window对象下的一个属性,使用的时候可以省略window对象
location可以获取或者设置浏览器地址栏的URL
location对象的成员

  • 使用chrome的控制台查看
  • 查MDN:developer.mozila.org/zh-CN/
  • 成员:assign()/reload()/replace()
    hash/host/hostname/search/href...
<input type="button" value="跳转" id="btn">
<script>
  var btn = document.getElementById("btn");
  btn.onclick = function () {
    // 输出URL地址
    // console.log(location.href);
    // 重新赋值,可以跳转到新页面,并且记录历史
    // location.href = "http://www.lagou.com";
    // assign 委派
    // assign() 方法的作用 与 href 属性一样,可以设置页面跳转的地址
    // location.assign("http://www.lagou.com");
    // replace 替换
    // 功能:替换掉地址栏中当前的网址,但是不记录历史
    // location.replace("http://www.lagou.com");
    // reload 重新加载
    // 类似 键盘中 f5 功能,类似于false效果, ctrl+f5 强制刷新,
    // 从服务器获取页面,相当于 true 的效果
    // 参数:true 强制从服务器获取页面,false 
    // 如果浏览器有缓存网页的话,会直接从缓存中获取页面
    location.reload(true);
  };
</script>

URL

统一资源定位符(UniformResourceLocator,,URL)
URL的组成:scheme://host:port/path?query#fragment
例如:www.lagou.com:80/a/b/index.h…
scheme:通信协议,常用的http,ftp,maito等
host:主机,服务器(计算机)域名系统(DNS)主机名或IP地址。
port:端口号,整数,可选,省略时使用方案的默认端囗,如http的默认端口为80。
path:路径,由零或多个'/'符号隔开的字符串,一般用来表示主机上的一个目录或文件地址。
query:查询,可选,用于给动态网页传递参数,可有多个参数,用'&'符号隔开,每个参数的名和值用'='符号隔开。例如:name=zs
fragment:信息片断,字符串,锚点

history对象

history对象是window对象下的一个属性,使用的时候可以省略window对象
history对象可以与浏览器历史记录进行交互,浏览器历史记录是对用户所访问的页面按时间顺序进行的记录和保存。
有以下几个方法:
back()
forward()
go()

first.html主要内容:

<h1>First</h1>
<a href="second.html">跳转到二级页面</a><br>
<input type="button" value="前进" id="btn">
<script>
  var btn = document.getElementById("btn");
  btn.onclick = function () {
    // 前进,查看之前记录的跳转后的页面
    // history.forward();
    history.go(1);
  };
</script>

seconde.html主要内容:

<h1>Second</h1>
<input type="button" value="后退" id="btn">
<script>
  var btn = document.getElementById("btn");
  btn.onclick = function () {
    // 回退历史记录访问
    // history.back();
    history.go(-1);
  };
</script>

一般情况下,不需要设置history对象,用系统自带的回退就可以。少数情况才需要设置。