# 通过事件操作 DOM

# 课程目标

掌握 JavaScript 事件的概念,并能写出基本的事件相关的代码 掌握如何通过 JavaScript 操作 DOM 的样式 熟悉 DOM 事件相关知识

# 事件机制

# 阅读

首先学习了解 JavaScript 事件的知识

# 编码

我们来继续用封装自己的小 jQuery 库来实现我们对于 JavaScript 事件的学习,还是在你的 util.js ,实现以下函数

// 给一个element绑定一个针对event事件的响应,响应函数为listener
function addEvent(element, event, listener) {
    // your implement
}

// 例如:
function clicklistener(event) {
    ...
}
addEvent($("#doma"), "click", a);

// 移除element对象对于event事件发生时执行listener的响应
function removeEvent(element, event, listener) {
    // your implement
}

接下来我们实现一些方便的事件方法

// 实现对click事件的绑定
function addClickEvent(element, listener) {
  // your implement
}

// 实现对于按Enter键时的事件绑定
function addEnterEvent(element, listener) {
  // your implement
}

接下来我们把上面几个函数和 $ 做一下结合,把他们变成 $ 对象的一些方法

  • addEvent(element, event, listener) -> $.on(element, event, listener);
  • removeEvent(element, event, listener) -> $.un(element, event, listener);
  • addClickEvent(element, listener) -> $.click(element, listener);
  • addEnterEvent(element, listener) -> $.enter(element, listener);

接下来考虑这样一个场景,我们需要对一个列表里所有的<li>增加点击事件的监听

最笨的方法

<ul id="list">
  <li id="item1">Simon</li>
  <li id="item2">Kenner</li>
  <li id="item3">Erik</li>
</ul>
function clickListener(event) {
  console.log(event);
}

$.click($("#item1"), clickListener);
$.click($("#item2"), clickListener);
$.click($("#item3"), clickListener);

上面这段代码要针对每一个 item 去绑定事件,这样显然是一件很麻烦的事情。

稍微好一些的

<ul id="list">
  <li>Simon</li>
  <li>Kenner</li>
  <li>Erik</li>
</ul>

我们试图改造一下

function clickListener(event) {
  console.log(event);
}

each($("#list").getElementsByTagName("li"), function(li) {
  addClickEvent(li, clickListener);
});

我们通过自己写的函数,取到 id 为 list 这个 ul 里面的所有 li ,然后通过遍历给他们绑定事件。这样我们就不需要一个一个去绑定了。但是看看以下代码:

<ul id="list">
    <li id="item1">Simon</li>
    <li id="item2">Kenner</li>
    <li id="item3">Erik</li>
</ul>
<button id="btn">Change</button>
function clickListener(event) {
    console.log(event);
}

function renderList() {
  // bca-disable-line
    $("#list").innerHTML = '<li>new item</li>';
}

function init() {
    each($("#list").getElementsByTagName('li'), function(item) {
        $.click(item, clickListener);
    });

    $.click($("#btn"), renderList);
}
init();

我们增加了一个按钮,当点击按钮时,改变 list 里面的项目,这个时候你再点击一下 li ,绑定事件不再生效了。那是不是我们每次改变了 DOM 结构或者内容后,都需要重新绑定事件呢?当然不会这么笨,接下来学习一下事件代理,然后实现下面新的方法:

// 先简单一些
function delegateEvent(element, tag, eventName, listener) {
  // your implement
}

$.delegate = delegateEvent;

// 使用示例
// 还是上面那段HTML,实现对list这个ul里面所有li的click事件进行响应
$.delegate($("#list"), "li", "click", clickHandle);

估计有同学已经开始吐槽了,函数里面一堆 $ 看着晕啊,那么接下来把我们的事件函数做如下封装改变:

$.on(selector, event, listener) {
    // your implement
}

$.click(selector, listener) {
    // your implement
}

$.un(selector, event, listener) {
    // your implement
}

$.delegate(selector, tag, event, listener) {
    // your implement
}

// 使用示例:
$.click("[data-log]", logListener);
$.delegate('#list', "li", "click", liClicker);

# JavaScript 操作 DOM 样式

# 阅读

接下来学习如何用 JavaScript 操作 DOM 样式

# 编码一

接下来我们练习一下通过 JavaScript 完成 DOM 节点的增加和删除,以及样式的控制。

参考 示例 DEMO (opens new window) 编码实现一个简易 TODO 待办管理小工具

<h1>Todo List</h1>
<form id="form">
      <input type="text" class="input" id="input" placeholder="Enter your todo" autocomplete="off">
      <ul class="todos" id="todos"></ul>
</form>

需求说明

  • 用户在输入框中输入要做的任务,键盘按回车,在输入框下方,id 为 tidos 的 ul 中添加一条表示任务 li 元素
  • 鼠标点击任务 li 元素,表示任务已经完成。相应样式变化:划掉任务,字体颜色也相应变成浅色

# 编码二

参考 示例 Demo (opens new window) 编码实现一个轮播图.

需求说明

  • 图片数量及 URL 均在 HTML 中写好
  • 可以配置轮播的顺序(正序、逆序)、是否循环、间隔时长
  • 图片切换的动画要流畅
  • 在轮播图下方自动生成对应图片的小点,点击小点,轮播图自动动画切换到对应的图片

# 编码三

使用 JavaScript 来实现一个简易的颜色选择器,在页面中以矩阵的方式显示数个颜色,当鼠标点击到某个颜色格子上时,改变页面背景为该色块的颜色

<p oncilck="showColorPicker()">改变背景颜色</p>;

function showColorPicker() {
  //JS动态生成含有729个色块,rgb值间隔为32的颜色选择器
}

需求说明

  • 在页面中使用 JavaScript 生成一个颜色选择器,按顺序产生颜色矩阵
  • 生成颜色时,分别在 RGB 项上以 32 为间隔,从 RGB(0, 0, 0) 遍历到 RGB(255, 255, 255),共生成 729 个颜色格子
  • 当鼠标移动到某个颜色格子上是,在页面某个地方显示三个数字,分别为当前鼠标选中颜色的 RGB 值
  • 示例 DEMO 仅作参考,css 样式背景颜色边框等可以按照自己的审美自行调整
  • 不使用任何第三方的布局或样式库
  • 不使用任何第三方的 JavaScript 库

# W3C

# 阅读

最后,可以通过阅读标准,加深理解。

# 提交

把你今天觉得做得最好的代码放在 Github 后进行提交。

# 总结

依然把今天的学习用时,收获,问题进行记录。

# 自测问题

我们有一个空的 DOM 元素 elem 和一个字符串 text。

下面这 3 个命令中的哪个命令做的是完全相同的事儿?

/* bca-disable */

elem.append(document.createTextNode(text))
elem.innerHTML = text
elem.textContent = text