BOM、打开和关闭窗口、定时器、BOM常用对象

263 阅读7分钟

1. BOM

BOM: Browser Object Model -> 专门操作浏览器窗口 / 软件的 API

1.1. window: 2 个角色
  1. 代替 ES 中的 global 充当全局作用域对象
  2. 封装所有 DOMBOMAPI
1.1.1 window 的功能
  • history: 保存当前窗口打开后, 成功访问的 URL 历史记录栈
  • location: 保存当前窗口正在打开的 URL 对象
  • document: 封装页面内容和 DOM API 的根对象
  • navigator: 保存浏览器的配置信息
  • screen: 保存客户端显示设备的信息
  • event: 定义事件对象

2. 打开和关闭窗口

  • 打开一个新窗口: window.open('url', name)
    • name: 新窗口在内存中的名称
      • 浏览器规定: 相同 name 的窗口只能打开 1 个, 后打开的会覆盖先打开的
      • 预定义值:
        1. _self: 用当前窗口的 name 打开新窗口
          • 结果: 新窗口覆盖当前窗口
        2. _blank: 不指定 name 属性, 让浏览器随机分配 name
          • 结果: 每个窗口的 name 都不一样 -> 可以打开多个窗口
  • 打开一个超链接: 4 种
    1. 在当前窗口打开, 可后退:
      • HTML: <a href="url" target="_self">超链接</a>
      • JS: window.open('url', '_self')
    2. 在当前窗口打开, 不可后退:
      • 当前窗口每打开一个新 URL, 都会将新的 URL 保存到 window.history
      • 如果新 URL 是追加进 window.history 中, 则可后退
      • 如果新 URL 将当前 URL 替换掉, 则不可后退
      • JS: window.location.replace('url')
    3. 在新窗口打开, 可打开多个:
      • HTML: <a href="url" target="_blank">超链接</a>
      • JS: window.open('url', '_blank')
    4. 在新窗口打开, 只能打开 1 个:
      • HTML: <a href="url" target="自定义name">超链接</a>
      • JS: window.open('url', '自定义name')

3. 定时器: 2 种

3.1. 周期性定时器
3.1.1. 什么是

让程序每间隔一段时间反复执行一项任务

3.1.2. 何时
  • 只要一项任务需要每间隔一段时间反复执行
3.1.3. 如何: 3 步
  1. 定义任务函数: function taskFun() { ...... }

    • 定义了定时器每次要执行的任务
  2. 启动定时器: var timer = setInterval(taskFun, 间隔时间)

    • 强调: taskFun 是回调函数, 不用加 ()

    • timer 是定时器序号, 在内存中唯一标识一个定时器的整数

    • 间隔时间为 ms

  3. 停止定时器: clearInterval(timer)

    • timer 是要停止的定时器序号
    • 停止定时器的 2 种方式:
      1. 手动停止: 用户通过操作来停止定时器
      2. 自动停止: 在任务函数中判断临界值
        • 只要达到临界值, 就自动停止定时器
    • 问题: 停止定时器不会自动清除 timer 变量( 序号 ), 有可能会影响其他定时器
      • 解决: 凡是停止定时器, 就需要手动清除 timer: timer = null
3.2. 一次性定时器
3.2.1. 什么是

程序先等待一段时间, 再自动执行一次任务

3.2.2. 何时
  • 先等待一段时间再自动执行一次
  • 自执行一次后, 自动停止
3.2.3. 如何: 3 步
  1. 定义任务函数: function taskFn() { ...... }
  2. 启动定时器: var timer = setTimeout(taskFn, 等待ms)
  3. 停止定时器: clearTimeout(timer)
3.2.4. 原理

定时器回调函数的执行顺序在主程序之后

  • 试题

    var a = 10
    function fun() { a = 100 }
    setTimeout(fun, 0)
    console.log(a) // 10
    

4. BOM 常用对象

4.1. history

保存当前窗口打开后成功访问过的 URL 的历史记录栈

  • history.go(n):
    • history.go(0): 刷新
    • history.go(-1): 后退
    • history.go(1): 前进
4.2. location

保存当前窗口正在打开的 URL 对象

  • 属性:

    • location.href: 获取 / 设置完整的 URL

    • location.protocol: 协议

    • location.host: 主机名

      • 包含: 主机名 + 端口号
    • location.hostnam: 仅主机名

    • location.port: 端口号

    • location.pathname: 相对路径

    • location.hash: 锚点地址

    • location.search: 获取 URL ? 后的查询字符串

  • 方法:

    • location.assign('url'): 在当前页面打开新的 URL
      • 其实相当于: location.href = 'url'
    • location.replace('url'): 在当前窗口打开新的 URL, 替换 history 中当前 URL, 实现禁止后退
    • location.reload(false / true): 刷新
  • 试题: 2 种刷新

    1. 默认刷新: 优先使用本地缓存中的文件 -> 除非文件比服务器上的旧, 才被迫下载新文件
      • F5
      • history.go(0)
      • location.reload()
    2. 强制刷新: 每次强制跳过浏览器本地缓存, 总是从服务器下载新文件
      • location.reload(true)
4.3. screen

保存客户端显示设备的信息

  • 获取屏幕宽度
    • CSS: 媒体查询
    • JS: screen.width
  • 获取屏幕的高度: screen.height
4.4. navigator

封装浏览器配置信息的对象

  • navigator.cookieEnabled: 判断是否启用了 cookie
  • navigator.plugins: 封装所有插件的集合
  • 判断浏览器的名称和版本:
    • navigator.userAgent: 保存浏览器内核, 名称, 版本号的字符串
4.5. 窗口大小与窗口位置
4.5.1. 窗口大小
  1. 完整窗口大小: window.outerWidth / window.outerHeight
  2. 完整显示区大小: window.innerWidth / window.innerHeight
4.5.2. 调整窗口大小
  • 在打开窗口时, 就规定大小
    • var config = "left=?, top=?, width=?, height=?" window.open('url', 'name', config)
  • 打开窗口后在调整 -> 被禁用
    • window.resizeTo(width, height)
    • window.resizeBy(width增量, height增量)
4.5.3. 窗口位置
  • 窗口距离屏幕上边的位置: window.screenTop / window.screenY
  • 窗口距离屏幕左边的位置: window.screenLeft / window.screenX
4.5.4. 调整窗口位置
  • window.moveTo(left, top)
  • window.moveBy(left增量, top增量)
4.6. event
4.6.1. 什么是

用户手动触发的或浏览器自己触发的页面状态的改变

  • 当事件发生时, 都可以执行事件处理函数来响应事件的操作
4.6.2. 绑定事件处理函数: 3 种
  1. HTML 中绑定: <Any on事件名='js语句'></Any> / <Any on事件名='js语句' />
    • Ex: <button onclick="fun()">按钮</button>
    • 问题: 不符合内容和行为分离的原则, 不便于维护
  2. JS 中绑定:
    1. on 事件名: elem.on事件名 = function () { // this 指代 elem }
      • 局限: 一个事件, 只能绑定一个处理函数
    2. addEventListener: 可一个事件同时绑定多个处理函数
      • elem.addEventListener('事件名', fn)
      • 还可以移出事件
        • elem.removeEventListener('事件名', 函数名)
      • 绑定有名函数, 先在外声明函数, 再添加函数名, 移出时也必须用函数名
        • 问题: 绑定时如果使用匿名函数, 移出时无法找到原函数
        • 解决: 如果一个处理函数可能被移除, 就必须用有名函数
4.6.3. 事件模型 / 周期: 3 个阶段
  1. 捕获: 由外向内, 记录各级父元素上绑定的事件处理函数 -> 只记录, 不触发
  2. 目标触发: 优先触发目标元素上的事件处理函数
  3. 冒泡: 由内向外, 安捕获顺序的反向, 依次执行父元素上的事件处理函数
  • IE8: 2 个阶段 -> 没有捕获阶段
4.6.4. 事件对象: e
  • 什么是: 事件发生时, 自动创建的, 封装事件信息的对象

  • 如何获得: 事件对象, 默认作为处理函数的第一个参数传入

    • 事件处理函数(e) { // e: 自动获得事件处理对象 }

    • IE8: 事件对象自动保存在全局变量 event

    • 兼容处理

      function eventHandler(e) {
        e = e || window.event
      }
      
  • 何时: 只要希望获得事件的数据, 或修改事件的默认行为时

    • 包括:
      • 取消冒泡: e.stopPropagation()
      • 利用冒泡:
        • 问题: 浏览器通过遍历方式查找事件处理函数执行, 添加的事件监听越多, 遍历越慢, 网页响应速度越慢
          • 优化: 尽量少的添加事件监听
          • 如何:
            1. 如果多个平级子元素绑定相同事件时, 可在父元素仅添加一个事件监听, 所有子元素共用
              • 问题:
                1. 如何获得目标元素:
                  • e.target
                2. 可能目标元素不是想要的, 就要先鉴别目标元素, 再决定是否执行操作
            2. 如果一个父元素下的子元素, 需要动态生成, 并绑定事件, 则必须将事件绑定在父元素上; 动态添加的子元素才能自动使用父元素上的事件, 而不需要反复单独绑定
      • 阻止默认行为: e.preventDefault()
        • 2 个典型应用:
          1. 阻止 a 元素作为按钮时, 自动添加 # 锚点地址
          2. 表单验证未通过时, 阻止默认提交
4.6.5. 事件坐标
  1. 相对于屏幕左上角: e.screenX / e.screenY
  2. 相对于文档显示区左上角: e.clientX / e.clientY
  3. 相对于当前元素左上角: e.offsetX / e.offsetY
4.6.6. 页面滚动
  • 事件: window.onscroll
  • 获得页面滚动的位置: document.body.scrollTop