1. 一、DOM 绑定事件<br />在上章节中,我们已经开始接触事件了,比如下面代码;<br />//监听input 输入事件<br />dom.addEventListener("input", function() {});<br />//监听鼠标放置,移动事件<br />dom.addEventListener("mouseover", function() {});

    我们看到 DOM 可以通过
    addEventListener(eventName, callback) 绑定 eventName 事件

    二、DOM 事件
    我们打印一下 DOM 事件对象,这个事件对象会通过回调函数参数传递给我们
    const h1 = document.querySelector(“h1”);
    h1.addEventListener(“click”, function (e) {
    console.log(e);
    });

    从这个结果可以看出,这是一个 MouseEvent,这个对象我们需要掌握其中几个关键属性

    图片.png
    那除了上面事件,还有哪些常用事件呢?看一下官方文档
    https://developer.mozilla.org/zh-CN/docs/Web/Events

    2.1 焦点事件
    focus:表单组件获取焦点事件 blur;表单组件失去焦点事件

    2.2 鼠标事件
    click: 点击事件
    dblclick:双击事件
    mousedown:在元素上按下任意鼠标按钮
    mouseenter:指针移到有事件监听的元素内。
    mouseleave:指针移除元素范围外
    mousemove:指针在元素内移动时持续触发
    mouseover:指针移到有事件监听的元素或者它的子元素内
    mouseout:指针移除元素,或者移到它的子元素上
    mouseup:在元素上释放任意鼠标按键。

    2.3 键盘事件
    keydown:键盘按下事件
    keyup:键盘释放事件

    2.4 视图事件
    scroll:文档滚动事件
    resize:窗口放缩事件

    2.5 资源
    load:资源加载成功的事件

    三、点击事件
    UCode 案例
    在 DOM 事件中,最常用的是点击事件,比如点击页面跳转,点击页面按钮进行操作等

    3.1 静态页面
    我们首先在不考虑事件的情况下,完成所有页面样式的展示。

    3.2 Like 按钮点击事件
    那我们该如何实现这个效果呢?
    1、点击按钮后,添加has-like class,再次点击(取消Like),删除has-like class
    2、点击按钮后,将数字+1,再次点击(取消Like),数字-1

    我们首先给按钮添加点击事件,并且利用hasLike 变量标识是否喜欢:
    图片.png
    3.3 根据 hasLike 修改页面信息
    第二步,根据 hasLike 的值,修改页面信息,我们继续完善代码:
    // 默认是未点击喜欢
    let hasLike = false;
    const likeBtn = document.querySelector(“.like-btn”);
    const likeBtnRight = likeBtn.querySelector(“.right”);
    likeBtn.addEventListener(“click”, function () {
    // 点击事件
    hasLike = !hasLike;
    if (hasLike) {
    likeBtn.classList.add(“has-like”);
    likeBtnRight.innerHTML = parseInt(likeBtnRight.innerText.trim()) + 1;
    } else {
    likeBtn.classList.remove(“has-like”);
    likeBtnRight.innerHTML = parseInt(likeBtnRight.innerText.trim()) - 1;
    } });

    3.4 点击三个点显示操作列表
    那我们该如何实现上面的效果呢?
    监听三个点的按钮,点击控制 options 区域的显示和隐藏,及 diaplay : block/none;
    代码相比上面稍简单一点,代码如下:
    let showMore = false;
    const moreBtn = document.querySelector(“.workspace-item-more .select”);
    const morePanel = document.querySelector(“.workspace-item-more .options”); moreBtn.addEventListener(“click”, function () {
    showMore = !showMore;
    // 控制morePanel的显示和隐藏
    if (showMore) {
    morePanel.style.display = “block”;
    } else {
    morePanel.style.display = “none”;
    }
    });

    3.5 总结
    其实这几个案例都可以总结成一句话
    监听 DOM 事件,使用 DOM 操作,修改 DOM 属性

    四、冒泡、捕获、委托
    我们想在整个工程模板上添加点击事件,跳转到对应的工程详情页面(在这里,我们用 https://www/youkeda.com 官网代替)。

    我们在JS 中对面板增加点击事件,代码如下:
    // ……..
    // 省略前面的代码

    const workspace = document.querySelector(‘.workspace’);
    workspace.addEventListener(‘click’ , function() {
    window.location.href = ‘https://www.youkeda.com‘;
    });

    4.1 冒泡
    因为点击事件触发 Like click 事件,再次触发 workspace click 事件,这就是事件冒泡

    从上到下,整个是和 button.like-btn 的DOM 树。
    1、点击事件触发 button.like-btn 监听事件
    2、冒泡找到其父亲节点,触发父亲节点的监听事件
    3、依次冒泡直到 html 根元素为止

    我们也可以用代码来认证我们的思考,依次在组件节点上添加点击事件,如下:
    图片.png
    很简单,阻止冒泡 - e.stopPropagation(); 我们改进一下代码,
    likeBtn.addEventListener(‘click’, function(e){
    //点击事件
    e.stopPropagation()

    // ……..省略
    })

    可以看到,最终点击Like 按钮,并不会导致页面跳转,也就是冒泡事件被阻止。

    我们上面使用的 addEventListener 是在冒泡阶段监听事件,如果想在捕获阶段监听事件,我们需要传递第三个参数为true, 代码如下:
    dom.addEventListener(‘click’, function() {}, true);

    4.2 委托
    委托其实是冒泡事件的一种应用,这个概念依赖于这样一个事实,如果你想要在大量子元素中单击任何一个都可以运行一段代码,您可以将事件监听器设置在其父节点上,并让子节点上发生的事件冒泡到父节点上,而不是每个子节点单独设置事件监听器。
    const box = document.querySelector(‘.box’);
    const imgArr = box.children;
    for(let i = 0; i < imgArr.length; i++){
    imgArr[i].addEventListener(‘click’, function() {
    document.body.style.backgroundImage = url(${imgArr[i].src});
    });
    }

    那我们利用委托应该怎么做呢?对,我们只需要监听box 即可,代码修改如下:

    const box = document.querySelector(‘.box’);
    box.addEventListener(‘click’, function(e) {
    // 注意box 区域比 img 大,如果点击在空白间隔区域,那么返回的节点将不会是IMG,需要特殊处理一下
    if(e.target.nodeName === ‘IMG’) {
    document.body.style.backgroundImage = url(${e.target.src});
    }
    });

    五、移动事件
    5.1 鼠标移动事件
    1、mouseenter:指针移到有事件监听的元素内
    2、mouseleave:指针移出元素范围外(不冒泡)。
    3、mousemove:指针在元素内移到时持续触发
    4、mouseover:指针移到有事件监听的元素或者它的子元素内
    5、mouseout:指针移出元素,或者移到它的子元素上

    5.2 我们来分类一下
    1、mousemove
    这个是鼠标移到事件,比较简单

    2、mouseenter/mouseleave
    这个是鼠标进入和离开事件,但是仅仅只作用于当前 DOM 节点,不会作用于其后代节点

    3、mouseover/mouseout
    这个也是鼠标进入和离开事件,但和 enter/leave 不同的是:此事件除了作用于当前 DOM 节点,也会同时作用于其后代节点

    在平时使用中,90%我们都只会使用 mouseover/mouseout,这个事件

    六、表单元素事件
    6.1 焦点事件
    我们先来看看获取焦点和失去两个事件 —-focus 和 blur ,非常简单,我们直接来看案例。
    我们给QQ 注册页的昵称输入框加入焦点事件:
    const nick = document.querySelector(‘input.nick’);
    nick.addEventListener(‘focus’ , function() {
    console.log(‘获取焦点’);
    });

    nick.addEventListener(‘blur’, function() {
    console.log(‘失去焦点’);
    });

    大家点击昵称输入框,然后点击其他区域,可以看到陆续打印一下信息:
    ‘获取焦点’
    ‘失去焦点’
    ‘获取焦点’
    ‘失去焦点’
    etc. . .

    内容值变化
    对于表单元素,有两种事件可以监听元素内容变化 —-input 和 change

    我们写个案例看看情况,仍然对昵称输入框加上上面两种事件的监听,代码如下:
    const nick = document.querySelector(‘input.nick’);
    nick.addEventListener(‘input’, function() {
    console.log(‘———input’);
    console.log(nick.value);
    });

    nick.addEventListener(‘change’ , function() {
    console.log(‘———change’);
    console.log(nick.value);
    });

    我们发现,只要在输入框里面输入值,就会触发 input 事件。而要等到输入框失去焦点,才会触发change 事件。

    我们总结下,这两种是事件的区别:
    图片.png

    七、滚动事件
    场景
    最后我们来学习下页面滚动事件,在什么时候需要使用监听滚动呢?
    一般用在哪些场景呢?我们来看一些案例

    7.1 无尽滚动
    我们在很多网站都看到过页面每次滚动到底部,会加载新内容,再次滚动到底部,又会加载新内容

    7.1.1 事件描述
    滚动事件,事件名称为 —-scroll。首先来看看事件如何处理和监听,我们以之前的前端基础课程中文章为例,加入JS代码如下:
    window.addEventListener(‘scroll’ , function () {
    console.log(window.scrollY);
    });

    7.1.2 无尽滚动
    那接下来我们加一下无尽滚动效果,当页面快滚动到底部时,添加新的文章内容到body中。

    window.addEventListener(‘scroll’ , function () {
    //可以通过clientHeight 获取内容高度
    const height = document.body.clientHeight;

    //通过screen.height 获取浏览器的高度
    const screenHeight = window.screen.height;

    //当距离底部的距离小于500时,触发页面新增内容
    if (height - window.scrollY - screenHeight < 500) {
    console.log(‘加载新文章内容’);
    // 在底部添加10 张图片
    const div = document.createElement(‘div’);
    let str = ‘’;
    for (let i = 0; i < 0; i++) {
    str += <br /> <img<br /> class="first"<br /> alt=""<br /> src="[https://document.youkeda.com/P3-1-HTML-CSS/1.8/1.jpg?x-oss-process=image/resize,h_300](https://document.youkeda.com/P3-1-HTML-CSS/1.8/1.jpg?x-oss-process=image/resize,h_300)"<br /> /><br />;
    }
    div.innerHTML = str;
    document.body.appendChild(div);
    }
    });

    1、内容高度 document.body.clientHeight
    2、浏览器高度 window.screen.height
    3、滚动距离 window.scrollY
    4、滚动距离底部距离 内容高度 - 浏览器高度 - 滚动距离

    其它事件
    1、键盘事件:https://developer.mozilla.org/zh-CN/docs/Web/API/KeyboardEvent