zoukankan      html  css  js  c++  java
  • Javascript自定义事件功能与用法实例分析

    自定义事件很难派上用场?

    为什么自定义事件很难派上用场,因为以前js不是模块化开发,也很少协作。因为事件本质是一种通信方式,是一种消息,只有存在多个对象,多个模块的情况下,才有可能需要用到事件进行通信。而现在有了模块化之后,已经可以使用自定义事件进行各模块间协作了。

    哪里用得到自定义事件?

    事件本质是一种消息,事件模式本质上是观察者模式的实现,那么用得上观察者模式的地方,自然也可以也可以用上事件模式。所以,如果:

    1、一个目标对象改变,需要多个观察者调整自身的。

    比如:我需要元素A点击之后,元素B显示鼠标的位置,元素C显示提示,元素D.....

    2、分模块协作需要解耦的

    比如:甲负责模块A,乙负责模块B,模块B需要A运行完之后才能运行

    传统的写法将逻辑写在一个方法里面:

    1
    2
    3
    4
    function doSomething(){
      A();
      B();
    }

    这样做每次扩展都要修改a的点击函数,不好扩展。

    自定义事件的写法

    1
    2
    3
    4
    5
    6
    7
    8
    //1、创建事件
    var clickElem = new Event("clickElem");
    //2、注册事件监听器
    elem.addEventListener("clickElem",function(e){
      //干点事
    })
    //3、触发事件
    elem.dispatchEvent(clickElem);

    可以看到,elem通过dispatchEvent方法触发的事件,只有elem上注册的监听器才能监听得到。这就很没意思了,自己发给自己消息,通知自己去干什么。

    创建自定义事件可参考: MDN : Creating_and_triggering_events

    应用

    从前面 js 自定义事件 的描述中知道:元素A通过dispatchEvent方法触发的事件,只有A上注册的监听器才能监听得到。

    我们想要的效果是,别的对象干了某件事之后, 发个消息给我们,好让我们能做相应的改变。要做到这样,也不是没办法:我们可以在一个公共对象上监听和触发事件,这就很有意义了。

    例子一:通知多个对象

    要实现 元素A点击之后,元素B显示鼠标的位置,元素C显示提示,可以这样写:

    文件:a.js

    1
    2
    3
    4
    5
    6
    7
    import b from "./b"
    import c from "./c"
    var a = document.getElementById("a");
    a.addEventListener("click",function(e){
      var clickA = new Event("clickA");
      document.dispatchEvent(clickA);
    });

    注意:import进来的变量虽然不使用,但是一定不能省略

    文件b.js:

    1
    2
    3
    4
    var b = document.getElementById("b");
    document.addEventListener("clickA",function(e){
      b.innerHTML = "(128,345)";
    })

    文件c.js:

    1
    2
    3
    4
    var c = document.getElementById("c");
    document.addEventListener("clickA",function(e){
      c.innerHTML = "你点了A";
    })

    这样写,三个模块之间完全不用关心对象,也不知道对方存在,耦合度非常的低,完全可以独立编写,不会互相影响。这其实就是一个观察者模式的实现。

    例子二:游戏框架

    要开发一个游戏,启动游戏,加载图片和音乐,加载完后,渲染场景和音效,加载和渲染由不同的人负责。可以这样写:

    文件:index.js

    1
    2
    3
    4
    5
    6
    7
    8
    import loadImage from "./loadImage"
    import loadMusic from "./loadMusic"
    import initScene from "./initScene" 
    var start = document.getElementById("start");
    start.addEventListener("click",function(e){
      console.log("游戏开始!");
      document.dispatchEvent(new Event("gameStart"));
    })

    文件:loadImage.js

    1
    2
    3
    4
    5
    6
    7
    8
    // 加载图片
    document.addEventListener("gameStart",function(){
      console.log("加载图片...");
      setTimeout(function(){
        console.log("加载图片完成");
        document.dispatchEvent(new Event("loadImageSuccess"));
      },1000);
    });

    文件:loadMusic.js

    1
    2
    3
    4
    5
    6
    7
    8
    //加载音乐
    document.addEventListener("gameStart",function(){
      console.log("加载音乐...");
      setTimeout(function(){
        console.log("加载音乐完成");
        document.dispatchEvent(new Event("loadMusicSuccess"));
      },2000);
    });

    文件:initScene.js

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    //渲染场景
    document.addEventListener("loadImageSuccess",function(e){
      console.log("使用图片创建场景...");
      setTimeout(function(){
        console.log("创建场景完成");
      },2000)
    });
    //渲染音效
    document.addEventListener("loadMusicSuccess",function(e){
      console.log("使用音乐创建音效...");
      setTimeout(function(){
        console.log("创建音效完成");
      },500)
    });

    加载模块和渲染模块互不影响,易于扩展。

    携带信息

    除此之外,事件还能传递自定义信息:

    1
    2
    var event = new CustomEvent('myEvent', { 'dataName': dataContent });
    document.dispatchEvent(event);

    (注意:传递自定义信息需要使用CustomEvent,而不是Event)

    然后在监听函数里取出:

    1
    2
    3
    document.addEventListener("myEvent",function(e){
      console.log(e.dataName);
    })
  • 相关阅读:
    编程之美 2.3寻找发帖‘水王’ 扩展问题
    编程之美:1.12 扩展问题 解答与思考
    编程之美:1.9高效率安排见面会 图的m着色问题 回溯法
    研究生毕业课题怎么确定(转)
    图模型的统计推断 inference in graphical models(马尔科夫链的推断)
    微信js-sdk注意事项
    bootstrap-material-design-个人总结
    前端页面优化
    Material Design
    马克飞象
  • 原文地址:https://www.cnblogs.com/login123/p/12061624.html
Copyright © 2011-2022 走看看