Skip to content

事件基础

HTML events are “things” that happen to HTML elements.

When JavaScript is used in HTML pages, JavaScript can “react” on these events.

An HTML event can be something the browser does, or something a user does.

Here are some examples of HTML events:

  • An HTML web page has finished loading
  • An HTML input field was changed
  • An HTML button was clicked
  • When a user clicks the mouse
  • When a web page has loaded
  • When an image has been loaded
  • When the mouse moves over an element
  • When an input field is changed
  • When an HTML form is submitted
  • When a user strokes a key

Often, when events happen, you may want to do something.

JavaScript lets you execute code when events are detected.

HTML allows event handler attributes, with JavaScript code, to be added to HTML elements.

事件是什么

在 JavaScript 中,一个事件包含 3 部分:

  • 事件主角:是按钮?还是 div 元素?还是其他?
  • 事件类型:是点击?还是移动?还是其他?
  • 事件过程:这个事件都发生了些什么?

JavaScript 常见的事件共有以下 5 种:

  • 鼠标事件
  • 键盘事件
  • 表单事件
  • 编辑事件
  • 页面事件

事件操作是 JavaScript 的核心,可以这样说:不懂事件操作,JavaScript 等于白学。

事件调用方式

在 JavaScript 中,调用事件的方式有两种:

  • 在 script 标签中调用事件
  • 在元素中调用

1、在 script 标签中调用事件,指的是在 <script></script> 标签内部调用事件。

html
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title></title>
    <script>
      window.onload = function () {
        // 获取元素
        var oBtn = document.getElementById("btn");
        // 为元素添加点击事件
        oBtn.onclick = function () {
          alert("马拉松派");
        };
      };
    </script>
  </head>

  <body>
    <input id="btn" type="button" value="弹出" />
  </body>
</html>

从本质上来说,这种事件调用方式用于操作元素的属性。只不过这个属性不是一般的属性,而是“事件属性”。上面这句代码的意思就是给元素的 onclick 属性赋值,这个值是一个函数。

一定要从操作元素的 HTML 属性这个角度来看待事件操作,这能让你对事件操作理解得更深。

2、在元素中调用事件,指的是直接在 HTML 属性中调用事件,这个属性又叫作“事件属性”。

html
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title></title>
    <script>
      function alertMes() {
        alert("马拉松派");
      }
    </script>
  </head>

  <body>
    <input type="button" onclick="alertMes()" value="弹出" />
  </body>
</html>

元素的事件属性,如此看来数量上应该是海量的。

小结:

在 script 标签中调用事件,我们需要使用 getElementById()getElementsByTagName() 等方法来获取想要的元素,然后才能对其进行事件操作。

在元素属性中调用事件,我们是不需要使用 getElementById()getElementsByTagName() 等方法来获取想要的元素的,因为系统已经知道事件的主角是哪个元素了。

在实际开发中,我们更倾向于在 script 标签中调用事件,因为这种方式可以使结构(HTML)与行为(JavaScript)分离,代码更具有可读性和维护性。

鼠标事件

事件说明
onclick鼠标单击事件
onmouseover鼠标移入事件
onmouseout鼠标移出事件
onmousedown鼠标按下事件
onmouseup鼠标松开事件
onmousemoven鼠标移动事件

举例:为 div 元素添加单击事件

html
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title></title>
    <style type="text/css">
      #btn {
        display: inline-block;
        width: 80px;
        height: 24px;
        line-height: 24px;
        font-family: 微软雅黑;
        font-size: 15px;
        text-align: center;
        border-radius: 3px;
        background-color: deepskyblue;
        color: White;
        cursor: pointer;
      }

      #btn: hover {
        background-color: dodgerblue;
      }
    </style>
    <script>
      window.onload = function () {
        var oDiv = document.getElementById("btn");
        oDiv.onclick = function () {
          alert("这是一个模拟按钮");
        };
      };
    </script>
  </head>

  <body>
    <div id="btn">调试代码</div>
  </body>
</html>

举例:鼠标移入和鼠标移出

html
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title></title>
    <script>
      window.onload = function () {
        var oP = document.getElementById("content");
        oP.onmouseover = function () {
          this.style.color = "red";
        };
        oP.onmouseout = function () {
          this.style.color = "black";
        };
      };
    </script>
  </head>

  <body>
    <p id="content">马拉松派</p>
  </body>
</html>

举例:鼠标按下和鼠标松开

html
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title></title>
    <script>
      window.onload = function () {
        var oDiv = document.getElementById("title");
        var oBtn = document.getElementById("btn");
        oBtn.onmousedown = function () {
          oDiv.style.color = "red";
        };
        oBtn.onmouseup = function () {
          oDiv.style.color = "black";
        };
      };
    </script>
  </head>

  <body>
    <h1 id="title">马拉松派</h1>
    <hr />
    <input id="btn" type="button" value="button" />
  </body>
</html>

键盘事件

在 JavaScript 中,常用的键盘事件共有两种:

  • 键盘按下:onkeydown
  • 键盘松开:onkeyup

举例:统计输入字符的长度

html
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title></title>
    <script>
      window.onload = function () {
        var oTxt = document.getElementById("txt");
        var oNum = document.getElementById("num");
        oTxt.onkeyup = function () {
          var str = oTxt.value;
          oNum.innerHTML = str.length;
        };
      };
    </script>
  </head>

  <body>
    <input id="txt" type="text" />
    <div>字符串长度为:<span id="num">0</span></div>
  </body>
</html>

点评:网页中实现了一个文本输入框 input 和一个自动计数器 span,给文本输入框的键盘松开事件定义了一个函数,该函数的功能就是 获取 当前文本输入框内的文本内容,并将文本长度信息设置为计数器的文本内容,显示在网页上。

实现原理:每输入一个字符,我们都需要敲击一下键盘;每次输入完成,也就是 松开 键盘时,都会触发一次 onkeyup 事件,计算一次字符串的长度。

注意,onkeyup 本身并不是一个计数器,onkeyup 本身是一个事件,事件绑定了一个函数;onkeyup 事件可以监听(键盘)和触发(函数),函数可以“统计”和“显示”。

举例:验证输入是否正确

html
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title></title>
    <script>
      window.onload = function () {
        var oTxt = document.getElementById("txt");
        var oDiv = document.getElementById("content");
        // 定义一个变量,保存正则表达式
        var myregex = /^[0-9]*$/;
        oTxt.onkeyup = function () {
          // 判断是否输入为数字
          if (myregex.test(oTxt.value)) {
            oDiv.innerHTML = "输入正确";
          } else {
            oDiv.innerHTML = "必须输入数字";
          }
        };
      };
    </script>
  </head>

  <body>
    <input id="txt" type="text" />
    <div id="content" style="color: red;"></div>
  </body>
</html>

键盘事件一般有两个用途:表单操作和动画控制

表单事件

在 JavaScript 中,常用的表单事件有 3 种:

  • onfocus 和 onblur
  • onselect
  • onchange

onfocus 表示获取焦点时触发的事件,而 onblur 表示失去焦点时触发的事件,两者是相反的操作。

onfocus 和 onblur 这两个事件往往都是配合一起使用的。例如用户准备在文本框中输入内容时,此时文本框会获得光标,就会触发 onfocus 事件。当文本框失去光标时,就会触发 onblur 事件。

并不是所有的 HTML 元素都有焦点事件,具有“获取焦点”和“失去焦点”特点的元素只有 2 种:

  • 表单元素(单选框、复选框、单行文本框、多行文本框、下拉列表)
  • 超链接

举例:搜索框

html
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title></title>
    <style type="text/css">
      #search {
        color: #bbbbbb;
      }
    </style>
    <script>
      window.onload = function () {
        // 获取元素对象
        var oSearch = document.getElementById("search");
        // 获取焦点
        oSearch.onfocus = function () {
          if (this.value == "百度一下,你就知道") {
            this.value = "";
          }
        };
        // 失去焦点
        oSearch.onblur = function () {
          if (this.value == "") {
            this.value = "百度一下,你就知道";
          }
        };
      };
    </script>
  </head>

  <body>
    <input id="search" type="text" value="百度一下,你就知道" />
    <input id="Button1" type="button" value="搜索" />
  </body>
</html>

在 JavaScript 中,当我们选中“单行文本框”或“多行文本框”中的内容时,就会触发 onselect 事件。用得少,了解即可。

在 JavaScript 中,onchange 事件常用于“具有多个选项的表单元素”的操作:

  • 单选框选择某一项时触发
  • 复选框选择某一项时触发
  • 下拉列表选择某一项时触发

举例:单选框

html
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title></title>
    <script>
      window.onload = function () {
        var oFruit = document.getElementsByName("fruit");
        var oP = document.getElementById("content");
        for (var i = 0; i < oFruit.length; i++) {
          oFruit[i].onchange = function () {
            if (this.checked) {
              oP.innerHTML = "你选择的是:" + this.value;
            }
          };
        }
      };
    </script>
  </head>

  <body>
    <div>
      <label><input type="radio" name="fruit" value="苹果" />苹果</label>
      <label><input type="radio" name="fruit" value="香蕉" />香蕉</label>
      <label><input type="radio" name="fruit" value="西瓜" />西瓜</label>
    </div>
    <p id="content"></p>
  </body>
</html>

在这里,我们首先使用 getElementsByName() 方法来获得具有同一个 name 属性值的表单元素,然后使用 for 循环遍历,目的是给每一个单选按钮都添加 onchange 事件。当我们选中任意一个单选按钮(也就是触发 onchange 事件)时,就判断当前单选按钮是否被选中(this.checked)。如果当前按钮被选中,就将选中的单选按钮的值(this.value)赋值给 oP.innerHTML。

举例:复选框的全选与反选

html
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title></title>
    <script>
      window.onload = function () {
        var oSelectAll = document.getElementById("selectAll");
        var oFruit = document.getElementsByName("fruit");
        oSelectAll.onchange = function () {
          // 如果选中,即 this.checked 返回 true
          if (this.checked) {
            for (var i = 0; i < oFruit.length; i++) {
              oFruit[i].checked = true;
            }
          } else {
            for (var i = 0; i < oFruit.length; i++) {
              oFruit[i].checked = false;
            }
          }
        };
      };
    </script>
  </head>

  <body>
    <div>
      <p>
        <label><input id="selectAll" type="checkbox" />全选/反选:</label>
      </p>
      <label><input type="checkbox" name="fruit" value="苹果" />苹果</label>
      <label><input type="checkbox" name="fruit" value="香蕉" />香蕉</label>
      <label><input type="checkbox" name="fruit" value="西瓜" />西瓜</label>
    </div>
  </body>
</html>

举例:下拉列表

html
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title></title>
    <script>
      window.onload = function () {
        var oList = document.getElementById("list");
        oList.onchange = function () {
          var link = this.options[this.selectedIndex].value;
          window.open(link);
        };
      };
    </script>
  </head>

  <body>
    <select id="list">
      <option value="http://wiki.marapython.com">马拉松派</option>
      <option value="http://www.ptpress.com.cn">人民邮电出版社有限公司</option>
    </select>
  </body>
</html>

当我们选择下拉列表的某一项时,就会触发 onchange 事件,然后就会在新的窗口打开对应的页面。

选择下拉列表的某一项时,触发的是 onchange 事件,而不是 onselect 事件。onselect 事件仅仅在选择文本框中的内容时才会触发,我们要清楚这两者的区别。

编辑事件

在 JavaScript 中,常用的编辑事件有 3 种:

  • oncopy
  • onselectstart
  • oncontextmenu
html
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title></title>
    <script>
      window.onload = function () {
        document.body.oncopy = function () {
          return false;
        };
      };
    </script>
  </head>

  <body>
    <div>不要用战术上的勤奋,来掩盖战略上的懒惰。</div>
  </body>
</html>

选取文本后点击鼠标右键,【复制】这个选项还可以点击,但实际上,点击【复制】选项后再粘贴,是粘贴不出内容来的。

html
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title></title>
    <script>
      window.onload = function () {
        document.body.onselectstart = function () {
          return false;
        };
      };
    </script>
  </head>

  <body>
    <div>一个人可能走得快,但是一群人却可以走得远。</div>
  </body>
</html>

防止页面内容被选取,从本质上来说也是为了防止用户复制内容。为了防止用户复制内容,我们有两种实现方式:oncopy 事件和 onselectstart 事件。可以两种方式同时使用吗?

html
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title></title>
    <script>
      window.onload = function () {
        document.oncontextmenu = function () {
          return false;
        };
      };
    </script>
  </head>

  <body>
    <div>每个人的人生掌握在自己的手里,而不是别人的评价里。</div>
  </body>
</html>

虽然鼠标右键的功能被禁止使用,但是我们依旧可以使用快捷键,如可以使用 Ctrl+C 快捷键来复制内容,使用 Ctrl+S 快捷键来保存网页等。

总而言之,oncopy、onselectstart 和 oncontextmenu 在大多数情况下都是用来保护版权的。不过为了实现更好的用户体验,我们还是少用为妙,除非是在迫不得已的情况下。

页面事件

在 JavaScript 中,常用的页面事件只有下面 2 个:

  • onload
  • onbeforeunload

在 JavaScript 中,onload 表示文档加载完成后再执行的一个事件。

并不是所有情况都需要用到 window.onload,一般地,只有在想要“获取页面中某一个元素”的时候才会用到。

html
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title></title>
    <script>
      var oBtn = document.getElementById("btn");
      oBtn.onclick = function () {
        alert("JavaScript");
      };
    </script>
  </head>

  <body>
    <input id="btn" type="button" value="提交" />
  </body>
</html>

当我们点击【提交】按钮时,浏览器会报错。这是因为在默认情况下,浏览器是从上到下来解析一个页面的。当解析到 var oBtn = document.getElementById("btn"); 这一句时,浏览器找不到 id 为 btn 的元素,就会感到很疑惑:没听说过有谁叫 btn 啊?

正确的解决方法就是使用 window.onload,实现代码如下:

html
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title></title>
    <script>
      window.onload = function () {
        var oBtn = document.getElementById("btn");
        oBtn.onclick = function () {
          alert("JavaScript");
        };
      };
    </script>
  </head>

  <body>
    <input id="btn" type="button" value="提交" />
  </body>
</html>

在这个例子中,浏览器从上到下解析到 window.onload 时,就会先不解析 window.onload 里面的代码,而是继续往下解析,直到把整个 HTML 文档解析完后才会回去执行 window.onload 里面的代码。待页面加载完毕,页面上有名有姓的元素,document 对象已经全部知悉,直接调用方法就可精准获取。

在 JavaScript 中,onbeforeunload 表示离开页面之前触发的一个事件。

html
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title></title>
    <script>
      window.onload = function () {
        alert("欢迎来到绿叶学习网!");
      };
      window.onbeforeunload = function (e) {
        e.returnValue = "记得下来再来喔!";
      };
    </script>
  </head>

  <body></body>
</html>

WARNING

离开页面之前触发的事件 window.onbeforeunload 貌似无效?