一.概述

1.文档对象模型(Document Object Model):是W3C组织推荐的处理可扩展标记语言(HTML,XML)的标准编程接口

2.W3C已经定义了一系列的DOM接口,通过这些接口可以改变网页的内容,结构和样式

(1)DOM主要用于操作元素

3.DOM树:DOM树中的所有内容都可以看作是对象

(1)文档:一个页面就是一个文档,DOM中使用document表示
(2)元素:页面中的所有标签都是元素,DOM中使用element表示
(3)节点:网页中所有的内容都是节点(标签,文本,属性,注释等),DOM中使用node表示
image.png

二.获取元素

1.根据ID获取:

(1)使用 document.getElementById():返回一个元素对象

  • console.dir():打印返回的元素对象 可以更好地查看里面的属性和方法

    1. //由于HTML从上到下执行,所以script要写在div标签的下边
    2. <div id="time">2022-5-51</div>
    3. <script>
    4. var a = document.getElementById('time');
    5. console.log(a);
    6. </script>

    2.根据标签名获取:

    (1)使用 document.getElementsByTagName():返回带有指定标签名的对象的集合,以伪数组的形式存储

  • 想要依次打印可以遍历

    1. <ul>
    2. <li>hello</li>
    3. <li>hello</li>
    4. <li>hello</li>
    5. <li>hello</li>
    6. <li>hello</li>
    7. </ul>
    8. <script>
    9. var list = document.getElementsByTagName('li');
    10. for (var i = 0;i<list.length;i++){
    11. console.log(list[i]);
    12. }
    13. </script>

    (2)document是获取页面所有的指定节点,想要获取某个元素的子元素指定就要用element.getElementById()

  • element是元素,该元素必须是指定的单个元素,不可以是伪数组

    1. <ul>
    2. <li>hello</li>
    3. <li>hello</li>
    4. <li>hello</li>
    5. <li>hello</li>
    6. <li>hello</li>
    7. </ul>
    8. <ol id="ol">
    9. <li>world</li>
    10. <li>world</li>
    11. <li>world</li>
    12. <li>world</li>
    13. <li>world</li>
    14. </ol>
    15. <script>
    16. var ol = document.getElementById('ol');
    17. console.log(ol.getElementsByTagName('li'));
    18. </script>

    3.通过HTML5新增方法获取:

    (1)使用 document.getElementsByClassName():返回指定类名的对象的集合,以伪数组的形式存储
    (2)document.querySelector(‘选择器’):根据指定选择器,返回第一个元素对象(只返回第一个)
    (3)document.querySelectorAll(‘选择器’):根据指定选择器,返回所有的元素对象的集合

    1. <div class="box"></div>
    2. <div class="box"></div>
    3. <div id="nav">
    4. <ul>
    5. <li>首页</li>
    6. <li>产品</li>
    7. </ul>
    8. </div>
    9. <script>
    10. var boxs = document.getElementsByClassName('box');
    11. console.log(boxs);
    12. var firstbox = document.querySelector('.box');
    13. console.log(firstbox);
    14. var nav = document.querySelector('#nav');
    15. console.log(nav);
    16. var box = document.querySelectorAll('.box');
    17. console.log(box);
    18. </script>

    4.特殊元素(body,html)获取:提供了专用方法

    (1)获取body元素:document.body;
    (2)获取html元素:document.documentElement;

    三.事件基础

    1.事件:可以被js侦测的行为,可理解为触发-响应机制

    2.事件组成:

    (1)事件源:事件被触发的对象
    (2)事件类型:如何触发 什么事件

  • 例如:鼠标点击还是鼠标经过

(3)事件处理程序:通过一个函数赋值的方式完成
(4)案例:

  1. <button id="a">唐伯虎</button>
  2. <script>
  3. var btn = document.getElementById('a');
  4. btn.onclick = function(){
  5. alert("秋香");
  6. }
  7. </script>

3.执行事件的步骤:

(1)获取事件源
(2)注册事件(绑定事件)
(3)采取函数赋值形式添加事件处理程序

4.常见的鼠标事件:

鼠标事件 触发条件
onclick 鼠标左键点击触发
onmouseover 鼠标经过触发
onmouseout 鼠标离开触发
onfocus 获得鼠标焦点触发
onblur 失去鼠标焦点触发
onmousemove 鼠标移动触发
onmouseup 鼠标弹起触发
onmousedown 鼠标按下触发

四.操作元素

1.改变元素内容:例如绑定鼠标点击事件,鼠标点击改变文字内容

(1)elements.innerText:不识别HTML标签 不保留空格和换行
(2)elements.innerHTML:识别HTML标签 保留空格和换行
(3)表单元素不能用innerHTML或innerText修改,要用value

2.修改元素属性:

(1)element.属性 = ‘属性值’;
(2)案例:点击按钮显示对应图片

  1. <button id="ldh">刘德华</button>
  2. <button id="zxy">张学友</button>
  3. <img src="a.jpg">
  4. <script>
  5. var ldh = document.getElementById('ldh');
  6. var zxy = document.getElementById('zxy');
  7. ldh.onclick = function() {
  8. img.src = 'b.jpg';
  9. }
  10. zxy.onclick = function() {
  11. img.src = 'a.jpg'
  12. }
  13. </script>

3.修改表单属性:

(1)利用DOM可以操作如下表单属性:type,value,checked,selected,disabled
(2)例如修改内容就用element.value=””;
(3)修改为禁用就用element.disable=true;
(4)就是元素.后可以跟(1)中提到的属性
(5)案例:仿京东实现密码的显示与隐藏

  1. <style>
  2. .box{
  3. position: relative;
  4. width: 400px;
  5. border-bottom: 1px solid #ccc;
  6. margin:100px auto;
  7. }
  8. .box input {
  9. width: 370px;
  10. height: 30px;
  11. border: 0;
  12. outline: none;
  13. }
  14. .box img{
  15. position: absolute;
  16. right: 2px;
  17. top:2px;
  18. width: 24px;
  19. height: 24px;
  20. }
  21. </style>
  22. </head>
  23. <body>
  24. <div class="box">
  25. <label for="">
  26. <img src="close.png" id= "eye">
  27. </label>
  28. <input type="password" id="pwd">
  29. </div>
  30. <script>
  31. var eye = document.getElementById('eye');
  32. var pwd = document.getElementById('pwd');
  33. var flag = 0;
  34. eye.onclick = function(){
  35. if (flag == 0){
  36. pwd.type = 'text';
  37. eye.src='open.png';
  38. flag = 1;
  39. }else{
  40. pwd.type = 'password';
  41. eye.src='close.png';
  42. flag = 0;
  43. }
  44. }
  45. </script>
  46. </body>

4.修改元素样式:大小颜色,位置等

(1)行内样式操作:element.style

  • 但是该方法只能获取和设置内联样式(行内样式)
  • 如果获取行内样式没有的值会返回null
  • 所以此方法可以设置多个样式,通过修改属性名或类名完成样式的修改

(2)getComputedStyle(元素/对象).属性

  • 该方法可用来读取外部样式
  • 但是只能读取,不能设置

(3)类名样式操作:element.className

  • 通过类名可以依据js代码修改多行,弥补了行内样式操作的缺点
  • 即使元素原本有类名,也可以使用,会将原有的类名覆盖,若想保留原来的类名,可以采用多类名,空格间隔那种,把原有类名也写上

(4)修改样式属性采取驼峰命名法:font-size写成FontSize
(5)用js改的样式是行内样式
(6)案例:点击隐藏盒子

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  6. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  7. <title>Document</title>
  8. <style>
  9. .box1{
  10. width: 15px;
  11. height: 15px;
  12. background-color: blue;
  13. float: left;
  14. }
  15. .box2{
  16. width: 200px;
  17. height: 200px;
  18. background-color: aquamarine;
  19. display: block;
  20. float: left;
  21. }
  22. </style>
  23. </head>
  24. <body>
  25. <div class="box1"></div>
  26. <div class="box2"></div>
  27. <script>
  28. var box1 = document.querySelector('.box1');
  29. var box2 = document.querySelector('.box2');
  30. box1.onclick = function(){
  31. box2.style.display = 'none';
  32. }
  33. </script>
  34. </body>
  35. </html>

(6)案例:文本框获得焦点隐藏原内容

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  6. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  7. <title>Document</title>
  8. </head>
  9. <body>
  10. <input type="text" name="" id="" value="手机">
  11. <script>
  12. var text = document.querySelector('input');
  13. //获得焦点
  14. text.onfocus = function() {
  15. if(this.value === '手机') {
  16. this.value = '';
  17. }
  18. }
  19. //失去焦点
  20. text.onblur = function() {
  21. if(this.value === '') {
  22. this.value = '手机';
  23. }
  24. }
  25. </script>
  26. </body>
  27. </html>

5.排他思想:

(1)同一组元素中想要某个元素实现某种样式,就用到循环的排他思想
(2)排他思想步骤:

  • 首先清除元素的全部样式
  • 再给当前元素配置样式

(3)注意:必须严格按照步骤执行,顺序不可颠倒
(4)案例:购物车全选和取消全选:

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  6. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  7. <title>Document</title>
  8. <style>
  9. * {
  10. padding: 0;
  11. margin: 0;
  12. }
  13. .wrap {
  14. width: 300px;
  15. margin: 100px auto 0;
  16. }
  17. table {
  18. border-collapse: collapse;
  19. border-spacing: 0;
  20. border: 1px solid #c0c0c0;
  21. width: 300px;
  22. }
  23. th,
  24. td {
  25. border: 1px solid #d0d0d0;
  26. color: #404060;
  27. padding: 10px;
  28. }
  29. th {
  30. background-color: #09c;
  31. font: bold 16px "微软雅黑";
  32. color: #fff;
  33. }
  34. td {
  35. font: 14px "微软雅黑";
  36. }
  37. tbody tr {
  38. background-color: #f0f0f0;
  39. }
  40. tbody tr:hover {
  41. cursor: pointer;
  42. background-color: #fafafa;
  43. }
  44. </style>
  45. </head>
  46. <body>
  47. <div class="wrap">
  48. <table>
  49. <thead>
  50. <tr>
  51. <th>
  52. <input type="checkbox" id="j_cbAll" />
  53. </th>
  54. <th>商品</th>
  55. <th>价钱</th>
  56. </tr>
  57. </thead>
  58. <tbody id="j_tb">
  59. <tr>
  60. <td>
  61. <input type="checkbox" />
  62. </td>
  63. <td>iPhone8</td>
  64. <td>8000</td>
  65. </tr>
  66. <tr>
  67. <td>
  68. <input type="checkbox" />
  69. </td>
  70. <td>iPad Pro</td>
  71. <td>5000</td>
  72. </tr>
  73. <tr>
  74. <td>
  75. <input type="checkbox" />
  76. </td>
  77. <td>iPad Air</td>
  78. <td>2000</td>
  79. </tr>
  80. <tr>
  81. <td>
  82. <input type="checkbox" />
  83. </td>
  84. <td>Apple Watch</td>
  85. <td>2000</td>
  86. </tr>
  87. </tbody>
  88. </table>
  89. </div>
  90. <script>
  91. // 由上面的复选框来控制下面复选框的全选与全不选
  92. var j_cbAll = document.querySelector('#j_cbAll'); // 获取上面的复选框
  93. var j_tb = document.querySelector('#j_tb').querySelectorAll('input'); // 获取下面的复选框
  94. // 给上面的 复选框添加点击事件
  95. j_cbAll.onclick = function() {
  96. for (var i = 0; i < j_tb.length; i++) {
  97. j_tb[i].checked = this.checked;
  98. }
  99. }
  100. // 给下面的每个复选框绑定点击事件
  101. for (var i = 0; i < j_tb.length; i++) {
  102. j_tb[i].onclick = function() {
  103. var flag = true;
  104. // 进行循环判定 如果有一个没有被选中 上面的则不会被选中
  105. for (var i = 0; i < j_tb.length; i++) {
  106. if (!j_tb[i].checked) {
  107. flag = false;
  108. break;
  109. }
  110. }
  111. j_cbAll.checked = flag;
  112. }
  113. }
  114. </script>
  115. </body>
  116. </html>

6.获取属性值:

(1)element.属性 //获取内置属性值(元素本身自带的属性)
(2)element.getAttribute(‘属性’); //主要获得自定义的属性(程序员自己设置的,不是class,id这种自带的)

  • 自定义属性的目的:是为了保存并使用数据,有些数据
  • 为了区分自定义属性,H5规定自定义属性以”data-“开头
  • H5新增获取自定义属性方法:element.dataset.属性 或 element.dataset[‘属性’]

    7.设置属性值:

    (1)element.属性 = ‘值’;
    (2)element.setAttribute(‘属性’,’值’); //主要针对自定义属性

    8.移除属性值:

    (1)element.removeAttribute(‘属性’);

    五.节点操作

    1.简介:

    (1)由于上述方法逻辑性不强且繁琐,所以有了新的方法:节点操作
    (2)节点操作是利用节点层级关系获取元素,逻辑性强
    (3)节点具备节点类型(nodeType),节点名称(nodeName),节点值(nodeValue)三个基本属性

  • 节点类型有:元素节点:nodeType为1,属性节点 nodeType为2,文本类型(空格,换行都算文本类型) nodeType为3

    2.节点层级:

    (1)父节点:node.parentNode //得到离node最近的父节点 找不到返回null

  • 例如:li.parentNode 取得离他最近的一个父节点

(2)子节点:node.childNodes //得到指定节点的所有子节点的集合,包含空格,换行等

  • 若想只获得元素节点,就用if判断他的nodeType是否为1
  • 还可以用node.children,只返回元素节点
  • node.firstChild //返回第一个子节点 ,包括所有节点
  • node.lastChild //返回第一个子节点 ,包括所有节点
  • node.firstElementChild //返回第一个元素节点
  • node.lastElementChild //返回最后一个元素节点
  • 开发中最常用的是:element.children[索引]

(3)兄弟节点:node.nextSibling //得到下一个节点,包括空格,换行 找不到返回null

  • node.previousSibling //得到上一个节点,包括空格,换行 找不到返回null
  • node.nextElementSibling //得到当前元素的下一个兄弟节点,找不到返回null
  • node.previousElementSibling //得到当前元素的上一个兄弟节点,找不到返回null

    3.节点操作:

    (1)创建节点:document.createElement(‘标签名’);
    (2)添加节点:node.appendChild(创建的节点):将一个节点添加到指定父节点的子节点列表的末尾

  • 还可以在指定元素的前面添加:node.insertBefore(创建的节点,指定元素)

(3)删除节点:node.removeChild(child) //从DOM中删除一个子节点,返回删除的节点
(4)复制节点:node.cloneNode() //返回一份复制的node,也叫克隆节点

  • 括号内什么都不填或者填入false就是浅拷贝,只复制节点,不复制内容
  • 括号内填入true就是深拷贝,内容和节点一起复制

(5)案例:发布与删除评论:

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  6. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  7. <title>Document</title>
  8. <style>
  9. li{
  10. background-color: pink;
  11. }
  12. </style>
  13. </head>
  14. <body>
  15. <textarea name="" id="">123</textarea>
  16. <button>发布</button>
  17. <ul>
  18. </ul>
  19. <script>
  20. var btn = document.querySelector('button');
  21. var text = document.querySelector('textarea');
  22. var ul = document.querySelector('ul');
  23. // 创建留言和删除留言
  24. btn.onclick = function(){
  25. if(text.value == ''){
  26. alert("你没有输入内容");
  27. return false;
  28. } else {
  29. var li = document.createElement('li');
  30. li.innerHTML = text.value + "<a href='javascript:;'>删除</a>";
  31. ul.insertBefore(li,ul.children[0]);
  32. var as = document.querySelectorAll('a');
  33. for (var i=0;i<as.length;i++) {
  34. as[i].onclick = function() {
  35. ul.removeChild(this.parentNode);
  36. }
  37. }
  38. }
  39. }
  40. </script>
  41. </body>
  42. </html>

4.三种创建元素方式的区别:

(1)document.write()

  • 是将内容直接写入页面的内容流
  • 如果页面文档流加载完毕,在调用这句话会导致页面重绘

(2)element.innerHTML()

  • 将内容写入某个节点,不会导致页面全部重绘
  • 创建多个元素效率高(不要拼接字符串,采用数组的形式拼接),结构稍微复杂

(3)document.createElement()

  • 创建多个元素效率稍微低一点,但是结构更清晰

    六.事件高级

    1.注册事件:给元素添加事件或绑定事件

    (1)传统方法:element.事件 = function(){}

  • 例如:btn.onclick = function(){}

  • 特点:注册事件的唯一性(同一个元素的同一个事件只能处理一个处理函数,最后注册的处理函数会覆盖之前的处理函数)

(2)方法监听注册方式:使用addEventListener()方法

  • 语法:eventTarget.addEventListener(type,listener,useCapture)
    • 该方法会将指定的监听器注册到eventTarget(目标对象)上,当该对象触发指定时间就会执行事件处理函数
    • type:事件类型字符串,比如click,mouseover (注意,不能带on)
    • listener:事件处理函数,事件发生时,会调用该监听函数
    • useCapture:表示是否在捕获阶段触发。可省略,布尔值,默认为false;
  • 同一个元素的同一个事件可以添加多个事件处理函数
  • 此方法的this指的是事件的对象

    2.删除事件:也叫解绑事件

    (1)传统方法:element.onclick = null;

  • 例如:div.onclick = null;

(2)方法监听注册方式:

  • 语法:eventTarget.removeEventListener(type,listener,useCapture)

    3.DOM事件流:

    (1)事件流描述的是从页面中接收事件的顺序
    (2)事件发生会在元素节点之间按照特定的顺序传播,这个传播过程即DOM事件流
    (3)DOM事件流的三个阶段:捕获阶段,目标阶段,冒泡阶段

  • 比如,给元素绑定一个事件,他会从上面的元素(由DOM最顶层节点)传递过来,由于上面的元素没有绑定事件,所以不会做出反应,传递到具体元素接受的过程叫做事件捕获(捕获阶段不会触发事件),接收后逐级传到DOM最顶层的过程叫事件冒泡,也就是后代元素绑定的事件被触发,其祖先元素的相同时间也会触发

  • JS代码只能执行捕获或冒泡的其中一个阶段
  • onclick只能得到冒泡阶段
  • 没有冒泡阶段的事件:onblur,onfocus,onmouseenter,onmouseleave

DOM - 图2

  1. a.onclick = function(event){ //需要传入事件对象,才能取消冒泡
  2. event = event || window.event;
  3. alert("我是span的");
  4. event.cancelBubble = true;
  5. }

4.事件对象(event):

(1)绑定事件时函数括号里的就是事件对象(括号内写event或evt或e就行,兼容性有问题,可以写成window.event)
(2)事件对象有了事件才会存在,系统自动创建,不需要我们传递
(3)事件对象是我们事件的一系列相关数据的集合,跟事件相关的,比如鼠标点击就包含了鼠标的坐标等相关信息
(4)事件发生后,跟事件相关的一系列信息数据的集合都会放到这个事件对象event里面,他有很多的属性和方法
(5)event主要代表事件的状态,跟时间相关的一系列信息的集合。

  • 鼠标事件对象用MouseEvent
  • 键盘事件对象用KeyboardEvent

(6)事件对象常见属性和方法:

  • e.target与this的区别
    • e.target返回的触发时间的对象
    • this返回的是绑定时间的对象

e2a4d7a115072cd09bc42f1ebed55e4.jpg

  • 阻止默认行为:例如点击超链接不跳转
  • return false可以阻止默认行为,但是函数内后边的代码就无法执行了

    5.事件委托(代理,委派)

    (1)原理:不是每个子节点都设置事件监听器,而是在将事件监听器设置在其父结点上,然后利用冒泡原理影响设置每个子节点
    (2)优点:减少事件绑定的次数,提高了程序的性能

    6.鼠标事件补充:

    (1)禁止鼠标右键菜单:contextmenu

  • 主要控制何时显示上下文菜单

    1. document.addEventListener('contextmenu',function(e){
    2. e.preventDefault();//取消默认事件
    3. })

    (2)禁止鼠标选中:selectstart

    1. document.addEventListener('selectstart',function(e){
    2. e.preventDefault();//取消默认事件
    3. })

    (3)鼠标事件对象:MouseEvent
    6d183fb035d111183ebc6f649c91a05.jpg

  • 其中x,y坐标都是针对可视窗口的上和左边缘而论

(4)鼠标移动事件:

  • mousemove:鼠标移动
  • mousedown:鼠标按下
  • mouseup:鼠标松开

(5)鼠标滚轮事件:

  • event.wheelDelta:获取滚动方向,正值为向上滚动,负值为向下滚动
    1. <!DOCTYPE html>
    2. <html lang="en">
    3. <head>
    4. <meta charset="UTF-8">
    5. <meta http-equiv="X-UA-Compatible" content="IE=edge">
    6. <meta name="viewport" content="width=device-width, initial-scale=1.0">
    7. <title>Document</title>
    8. <style>
    9. body{
    10. height: 1000px;
    11. }
    12. img{
    13. width: 200px;
    14. position: absolute;
    15. }
    16. </style>
    17. </head>
    18. <body>
    19. <img src="./OIP-C.jpg" alt="">
    20. <script>
    21. var pic = document.querySelector('img');
    22. document.addEventListener('mousemove',function(e){
    23. var x = e.pageX;
    24. var y = e.pageY;
    25. pic.style.left = x + 'px';
    26. pic.style.top = y + 'px';
    27. })
    28. </script>
    29. </body>
    30. </html>

    7.常用键盘事件:

    | 键盘事件 | 触发条件 | | —- | —- | | onkeyup | 某个键盘按钮被松开时触发 | | onkeydown | 某个键盘按钮被按下时触发 | | onkeypress | 某个键盘按钮被按下时触发(不识别功能键,例如ctrl,shift等) | | keyCode | 返回该键的ASCII的值 |

(1)如果使用addEventListener不需要加on
(2)三个时间的执行顺序:keydown-keypress-keyup
(3)键盘控制盒子移动:

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  6. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  7. <title>Document</title>
  8. <style>
  9. .bigBox {
  10. width: 800px;
  11. height: 600px;
  12. border: 2px solid brown;
  13. margin: 0 auto;
  14. margin-top: 100px;
  15. position: relative;
  16. }
  17. .smallBox {
  18. width: 50px;
  19. height: 50px;
  20. background-color: khaki;
  21. position: absolute;
  22. left: 50px;
  23. top: 50px;
  24. }
  25. </style>
  26. </head>
  27. <body>
  28. <div class="bigBox">
  29. <div class="smallBox"></div>
  30. </div>
  31. <script>
  32. // 键盘按下事件 ←37 ↑38 →39 ↓40
  33. // 获取元素节点
  34. var smallBox = document.getElementsByClassName("smallBox")[0];
  35. var bigBox = document.getElementsByClassName("bigBox")[0];
  36. class Key {
  37. constructor(smallBox, bigBox) {
  38. this.smallBox = smallBox;
  39. this.bigBox = bigBox;
  40. document.onkeydown = this.keyDown.bind(this);
  41. }
  42. keyDown(ev) {
  43. this.ev = ev;
  44. // 获取小盒子的left值与top值。 注意 元素.style.属性名 只能获取行内样式。
  45. var l = parseInt(getComputedStyle(smallBox).left);
  46. var t = parseInt(getComputedStyle(smallBox).top);
  47. // console.log("l="+l);
  48. // console.log("t="+t);
  49. // 小盒子每次移动的距离
  50. var speed = 50;
  51. if (ev.shiftKey) {
  52. speed *= 2;
  53. }
  54. switch (ev.keyCode) {
  55. // 左
  56. case 37:
  57. // 小盒子应该向左移动
  58. l -= speed
  59. if (l >= 0) {
  60. smallBox.style.left = l + "px";
  61. } else {
  62. smallBox.style.left = 0;
  63. }
  64. break;
  65. // 上
  66. case 38:
  67. t -= speed;
  68. if (t >= 0) {
  69. smallBox.style.top = t + "px";
  70. } else {
  71. smallBox.style.top = 0;
  72. }
  73. break;
  74. // 右
  75. case 39:
  76. l += speed;
  77. if (l <= (bigBox.clientWidth - smallBox.offsetWidth)) {
  78. // 小盒子应该向右移动
  79. smallBox.style.left = l + "px";
  80. } else {
  81. smallBox.style.left = (bigBox.clientWidth - smallBox.offsetWidth) + "px";
  82. }
  83. break;
  84. // 下
  85. case 40:
  86. t += speed;
  87. if (t <= (bigBox.clientHeight - smallBox.offsetHeight)) {
  88. smallBox.style.top = t + "px";
  89. } else {
  90. smallBox.style.top = (bigBox.clientHeight - smallBox.offsetHeight) + "px";
  91. }
  92. break;
  93. }
  94. }
  95. }
  96. var key = new Key(smallBox, bigBox);
  97. </script>
  98. </body>
  99. </html>