本章目标

  • 了解什么是 DOM
  • 掌握常用的 DOM 操作
  • 会使用定时器

    本章任务

  • 完成打地鼠游戏

image.png

DOM

DOM 简介

DOM 概念

DOM 是 JavaScript 操作网页的接口API,全称为“文档对象模型”(Document Object Model)。它的作用是将网页转为 JavaScript 对象,从而可以用脚本进行各种操作(比如增删内容)。

浏览器会根据 DOM 模型,将结构化文档(比如 HTML 和 XML)解析成一系列的节点,再由这些节点组成一个树状结构(DOM Tree)。所有的节点和最终的树状结构,都有规范的对外接口。
image.png

DOM 只是一个接口规范,可以用各种语言实现。所以严格地说,DOM 不是 JavaScript 语法的一部分,但是 DOM 操作是 JavaScript 最常见的任务,离开了 DOM,JavaScript 就无法控制网页。另一方面,JavaScript 也是最常用于 DOM 操作的语言。后面介绍的就是 JavaScript 对 DOM 标准的实现和用法。

节点

DOM 的最小组成单位叫做节点(node)。文档的树形结构(DOM 树),就是由各种不同类型的节点组成。每个节点可以看作是文档树的一片叶子。节点也是对象。

image.png

常用的 DOM 操作

获取元素

  1. // 根据id获取一个DOM对象
  2. let div = document.querySelector('#box')
  3. // 根据类选择器获取一些DOM元素
  4. let list = document.querySelectorAll('.item')
  5. // 遍历list中的每一个 DOM 元素
  6. list.forEach(function (item) {
  7. console.log(item)
  8. })

设置属性

  1. // 根据id获取一个DOM对象
  2. let div = document.querySelector('#box')
  3. // 设置div之间的内容
  4. div.textContent = '疫情封城去哪买菜?'
  5. // 设置图片
  6. let img = document.querySelector('.image')
  7. img.src = 'images/01.jpg'
  8. let btn = document.querySelector('.btn')
  9. // 禁用按钮
  10. btn.disabled = true

事件机制

  1. let btn = document.querySelector('.btn')
  2. // 给按钮注册点击事件
  3. btn.onclick = function () {
  4. console.log('别点我,疼')
  5. }

定时器

window 对象提供了两种类型的定时器,分别是可以实现在指定时间后执行特点操作,也可以让代码每隔一段时间执行一次,实现间隔执行操作。

延迟执行定时器

如果我们要实现购买成功之后,延迟 5s 之后跳转到其它页面,这个时候可以使用延迟执行的定时。
setTimeout() 方法可以创建一个定时器,让代码延迟一段时间执行。

下面先来介绍 setTimeout() 的语法:

  1. const timerId = window.setTimeout(func[, delay]);
  • 参数:
    • 第一个参数 func,时间到达之后执行的函数
    • 第二个参数 delay,延迟的毫秒数(一秒等于1000毫秒),如果省略该参数默认为0,表示马上、尽可能快的执行。

浏览器中调用定时器的最小时间间隔是4毫秒

  • 返回值:
    • 返回值 timerId 是一个正整数,表示定时器的编号。这个值可以传递给 clearTimeout() 来取消该定时器

定时器在时间为到达的时候可以通过 clearTimeout() 取消定时器的执行,下面来演示定时器的用法:

  1. const timerId = setTimeout(print, 5000);
  2. function print() {
  3. console.log('时间到达5秒')
  4. }
  5. btn.onclick = function () {
  6. // 取消定时器
  7. clearTimeout(timerId);
  8. };

从上面代码可以看出 setTimeout() 在等待5秒后会执行一次操作然后停止定时器。

模拟商品购买成功后,5s 跳转到其它页面:

  1. setTimeout(function () {
  2. location.href = 'index.html';
  3. }, 5000);

间隔执行定时器

setInterval() 是间隔执行定时器,会间隔指定时间重复执行操作,使用方式和 setTImeout() 相似。网页上显示的倒计时效果、包括一些 JavaScript 实现的动画效果都离不开 setInterval()。

下面来样式 setInterval() 的用法:

  1. const timerId = window.setInterval(func, delay);
  • 参数:
    • 第一个参数 func,时间到达指定毫秒数后重复执行的函数
    • 每次延迟的毫秒数 (一秒等于1000毫秒),函数的每次调用会在该延迟之后发生。和setTimeout一样,实际的延迟时间可能会稍长一点。这个时间计算单位是毫秒(千分之一秒),这个定时器会使指定方法或者代码段执行的时候进行时间延迟。如果这个参数值小于10,则默认使用值为10。请注意,真正延迟时间或许更长
  • 返回值:
    • 返回值 timerId 是一个非零数值,用来标识通过 setInterval()创建的计时器,这个值可以用来作为 clearInterval() 的参数来清除对应的计时器

和 setTimeout 类似,可以通过 clearInterval() 终止定时器的执行,下面来演示 setInterval() 的使用:

  1. const timerId = setInterval(print, 2000);
  2. function print() {
  3. console.log('两秒钟打印一次');
  4. }
  5. btn.onclick = function () {
  6. clearInterval(timerId);
  7. }

打地鼠游戏

页面搭建

网页背景

  1. * {
  2. margin: 0;
  3. padding: 0;
  4. }
  5. html,
  6. body {
  7. height: 100%;
  8. }
  9. body {
  10. background: #ebf9ff url(./images/bg.jpg) no-repeat center center;
  11. /* overflow: hidden; */
  12. }

顶部说明

  1. <div class="top">
  2. <h4>
  3. 游戏说明:
  4. </h4>
  5. <p>
  6. 点击“开始游戏”按钮,在下图中随机产生老鼠,老鼠消失前单击老鼠进行击打,
  7. 打中一次即可获得100的积分。快快行动吧,考验您的
  8. 反应和眼力!
  9. </p>
  10. </div>
  1. .top {
  2. width: 50%;
  3. color: #666;
  4. margin: 0 auto;
  5. padding-top: 20px;
  6. }

得分情况

  1. <div class="main">
  2. <div class="sidebar">
  3. <p>游戏时间: <input type="text" id="game" value="1"> 分钟</p>
  4. <p>间隔时间: <input type="text" id="interval" value="1"> 秒数</p>
  5. <p>停留时间: <input type="text" id="stay" value="1"> 秒数</p>
  6. <p>倒计时间: <span id="count">60</span></p>
  7. <div class="score">得分情况:
  8. <div>
  9. <p>打中:<span id="dz">0</span>只 漏掉:<span id="ld">0</span></p>
  10. <p>总分:<span id="zf">0</span>分 得分:<span id="df">0</span></p>
  11. </div>
  12. </div>
  13. <p class="btn-wrap">
  14. <input type="button" id="btnStart" value="开始游戏">
  15. <input type="button" id="btnStop" value="停止游戏">
  16. </p>
  17. </div>
  18. </div>
  1. .main {
  2. width: 750px;
  3. margin: 80px auto;
  4. color: #333;
  5. }
  6. .main .sidebar {
  7. float: left;
  8. }
  9. .main .sidebar .score {
  10. color: red;
  11. }
  12. .main .sidebar .btn-wrap {
  13. text-align: center;
  14. }

游戏区域

  1. <div class="main">
  2. ……
  3. <div class="game">
  4. <div class="box">
  5. <div class="item"><img src="" alt="" class="image"></div>
  6. <div class="item"><img src="" alt="" class="image"></div>
  7. <div class="item"><img src="" alt="" class="image"></div>
  8. <div class="item"><img src="" alt="" class="image"></div>
  9. <div class="item"><img src="" alt="" class="image"></div>
  10. <div class="item"><img src="" alt="" class="image"></div>
  11. <div class="item"><img src="" alt="" class="image"></div>
  12. <div class="item"><img src="" alt="" class="image"></div>
  13. <div class="item"><img src="" alt="" class="image"></div>
  14. <div class="item"><img src="" alt="" class="image"></div>
  15. <div class="item"><img src="" alt="" class="image"></div>
  16. <div class="item"><img src="" alt="" class="image"></div>
  17. <div class="item"><img src="" alt="" class="image"></div>
  18. <div class="item"><img src="" alt="" class="image"></div>
  19. <div class="item"><img src="" alt="" class="image"></div>
  20. <div class="item"><img src="" alt="" class="image"></div>
  21. <div class="item"><img src="" alt="" class="image"></div>
  22. <div class="item"><img src="" alt="" class="image"></div>
  23. <div class="item"><img src="" alt="" class="image"></div>
  24. <div class="item"><img src="" alt="" class="image"></div>
  25. <div class="item"><img src="" alt="" class="image"></div>
  26. <div class="item"><img src="" alt="" class="image"></div>
  27. <div class="item"><img src="" alt="" class="image"></div>
  28. <div class="item"><img src="" alt="" class="image"></div>
  29. <div class="item"><img src="" alt="" class="image"></div>
  30. </div>
  31. </div>
  32. </div>
  1. .main .game {
  2. float: left;
  3. width: 360px;
  4. height: 360px;
  5. margin-left: 40px;
  6. }
  7. .main .game .item {
  8. box-sizing: border-box;
  9. float: left;
  10. width: 70px;
  11. height: 70px;
  12. padding-top: 3px;
  13. border: 1px solid #eee;
  14. background-color: #c6db56;
  15. text-align: center;
  16. }
  17. .main .game .item .image {
  18. cursor: pointer;
  19. }

打地鼠游戏实现

定义变量

  1. // 时间
  2. let gameTime, intervalTime, stayTime, count
  3. // 分数
  4. let sumNumber, number
  5. let timerId, currentIndex
  6. // 按钮
  7. let btnStart, btnStop
  8. btnStart = document.querySelector('#btnStart')
  9. btnStop = document.querySelector('#btnStop')
  10. btnStop.disabled = true

初始化

  1. function init () {
  2. // 文本框
  3. const game = document.querySelector('#game')
  4. const interval = document.querySelector('#interval')
  5. const stay = document.querySelector('#stay')
  6. // 倒计时,游戏时间倒计
  7. const countSpan = document.querySelector('#count')
  8. game.disabled = true
  9. interval.disabled = true
  10. stay.disabled = true
  11. // 秒
  12. gameTime = game.value * 60
  13. // 毫秒
  14. intervalTime = interval.value * 1000
  15. stayTime = stay.value * 1000
  16. count = gameTime
  17. // 倒计时时间
  18. countSpan.textContent = gameTime
  19. btnStart.disabled = true
  20. btnStop.disabled = false
  21. }

点击开始按钮

  1. btnStart.onclick = function () {
  2. init()
  3. startGame()
  4. }
  1. function startGame() {
  2. random()
  3. // 开启定时器
  4. timerId = setInterval(() => {
  5. // 时间到达后停止
  6. count--
  7. random()
  8. const countSpan = document.querySelector('#count')
  9. countSpan.textContent = count
  10. if (count == 1) {
  11. // stopGame()
  12. alert('游戏结束')
  13. }
  14. }, intervalTime);
  15. }
  1. // 随机位置
  2. function random () {
  3. currentIndex = parseInt(Math.random() * 25)
  4. const images = document.querySelectorAll('.game .image')
  5. const img = images[currentIndex]
  6. img.src = 'images/01.jpg'
  7. // 1秒后清除
  8. clearImage(img)
  9. }
  1. function clearImage (img) {
  2. setTimeout(() => {
  3. img.src = ''
  4. // -100 防止两次随机数字相同,这样的话第二次的地鼠看不到
  5. }, intervalTime - 100);
  6. }

计算得分

  1. // 计算分数
  2. function setScore () {
  3. const dz = document.querySelector('#dz')
  4. const ld = document.querySelector('#ld')
  5. const zf = document.querySelector('#zf')
  6. const df = document.querySelector('#df')
  7. dz.textContent = number
  8. ld.textContent = sumNumber - number
  9. zf.textContent = sumNumber * 100
  10. df.textContent = sumNumber * 100
  11. }
  1. // startGame 中调用
  2. function startGame() {
  3. sumNumber = 0
  4. number = 0
  5. setScore()
  6. ……
  7. // 开启定时器
  8. timerId = setInterval(() => {
  9. ……
  10. // 计算分数
  11. sumNumber++
  12. setScore()
  13. ……
  14. }, intervalTime);
  15. }

停止游戏

  1. btnStop.onclick = function () {
  2. stopGame()
  3. }
  1. function stopGame () {
  2. if (!timerId) return
  3. btnStart.disabled = false
  4. btnStop.disabled = true
  5. const game = document.querySelector('#game')
  6. const interval = document.querySelector('#interval')
  7. const stay = document.querySelector('#stay')
  8. game.disabled = false
  9. interval.disabled = false
  10. stay.disabled = false
  11. count.textContent = gameTime
  12. clearInterval(timerId)
  13. }

打地鼠

  1. // 给所有img注册事件
  2. // 给所有的imgs注册点击事件
  3. const images = document.querySelectorAll('.box .image')
  4. images.forEach(item => {
  5. item.onclick = function () {
  6. const src = this.src
  7. if (src !== '') {
  8. this.src = './images/02.jpg'
  9. number++
  10. setTimeout(() => {
  11. this.src = ''
  12. }, 500)
  13. }
  14. }
  15. })