代码之家  ›  专栏  ›  技术社区  ›  tkotitan

你能让我很容易地理解动态、抽象的事件对象吗?

  •  2
  • tkotitan  · 技术社区  · 17 年前

    我使用MFC为GUI按钮编写了C++事件驱动的应用程序,并使用onmousedown等HTML事件来触发网页中的一些Javascript。当您使用界面并且事件是硬编码的时,事件驱动编程的想法是直观的。

    我知道如何在C中使用函数指针,我也看到Windows如何使用它们来运行事件循环。我可以编写代码来动态调用不同的函数。

    我的问题是,从编译时转移到运行时。我在这里说的是任何语言,但如果你需要一种语言,请选择Javascript或PHP,因为我现在最常用它们。我完全不知道如何使用我自己的事件对象来完成某件事。这不是我理解的概念。由于我不使用它们,我不知道它们的实际用途是什么。

    例如,我想,如果我想制作一个自定义的回合制游戏,我可能会使用事件对象来表示一些只需要“发生”的游戏片段能力的效果

    有人能给我一个简单的自定义事件用法吗?或者它有用或实用的情况?它在很大程度上取决于语言和环境以及如何处理事件吗?Javascript的答案很好,但我读过很多语言。

    对不起,我只是在这方面有所欠缺,需要一些实用、高级(中级?)的见解。这就像C中的指针。我“得到”指针,知道它们是你的朋友。但有一段时间我没有,我认识的很多人仍然没有。一旦你得到了它,这很简单,我只是没有得到定制的、动态的事件。

    6 回复  |  直到 17 年前
        1
  •  5
  •   Christian Nunciato    17 年前

    当我们谈论面向事件的编程时,我们通常谈论的是 observer design pattern 观测器设计模式的一个目标是实现 loose coupling 物体之间。

    • 确保爸爸有Rover的引用,当他回家时,调用Rover的greetDatAtTheDoor()方法,或者

    • 给罗孚一个爸爸的推荐信, greetDadAt TheDoor()内部。

    从表面上看,两者之间似乎没有太大区别,但实际上,爸爸已经把罗孚的一些实施方式烧到了心里;如果Rover的实现因某种原因必须更改,我们必须在两个地方进行更改:一次是在Rover,然后是在Dad。也许没什么大不了的,但仍然不理想。

    现在想象一下,妈妈也想问候爸爸。那只猫,Bigglesworth先生,不太喜欢爸爸,想确保他不在身边,所以他宁愿出去。邻居乔想知道爸爸什么时候回家,这样他就可以问爸爸欠他的二十美元了。我们如何解释所有这些情况,以及不可避免地会出现的其他情况?在爸爸的类定义中引用妈妈的greetHusand()方法、猫的getOutNow()方法,狗的greetDadAtTheDoor()方法和乔的goGetMyOne()方法会很快把爸爸的事情搞砸——而且没有好的理由,因为爸爸真正需要做的就是回家。妈妈、狗、猫和邻居只是想在发生这种情况时得到通知,这样他们就可以做任何内部实现所需的事情。

    语言以不同的方式处理这些东西的细节,但当你开始谷歌搜索时,你会看到,这种模式通常涉及到事件“调度器”(在这种情况下,爸爸——即其他人感兴趣的对象)和“订阅者”(例如,妈妈、猫、罗孚和乔)上有一个数组或类似数组的结构,所有这些都是通过调用调度器上公开的方法并传递对自己的引用来“注册”的——这些引用最终以某种形式出现在爸爸的“订阅者”数组中。然后,当爸爸回家时,他“分派”了一个事件——比如“我回家了!”事件——这本质上是一个循环函数对他的每个订阅者进行访问,并用他们自己的一些可公开访问的方法调用它们——只是这个方法的名字爸爸不知道,也不必知道,因为监听器在他/她/它传入时提供了它。

    var dad:Dad = new Dad();
    dad.addEventListener(DadEvent.ARRIVED_HOME, greetHusbandAtDoor);
    
    private function greetHusbandAtDoor(event:DadEvent):void
    {
       // Go greet my husband
    }
    

    那么,在爸爸身上,当我回家时,我所要做的就是:

    dispatchEvent(new DadEvent(DadEvent.ARRIVED_HOME));
    

    …而且因为Flash为我处理事件调度和通知细节(同样,每个人的做法都有点不同,但在内部,Flash遵循我描述的概念模型),我爸爸回家后,每个家庭成员都会自动完成它注册要做的事情。

        2
  •  2
  •   Bermo    5 年前

    使用事件构建功能有两个方面。第一个是定义事件发生的条件。在浏览器中的javascript中,没有一个 mousedown bubbling 这与此有关。但这超出了范围)。

    因此,对于堆栈溢出,每个向下箭头上都有一个事件处理程序 onclick

    jQuery("a .downarrow")
    .click(function(e){ e.target.style.color="red" /* ... do other things */ });
    

    或者在原始JavaScript(版本1.6)中,它可能是

    Array.prototype.slice.apply(document.getElementsByTagName("a"))
    .filter(function(o){ return !!(/downarrow/).exec(o.className)})
    .forEach(function(o){ 
        o.onclick= function(e){ 
            e.target.style.color="red" /* ...do other things * / 
        }
     });
    

    事情就是这么简单。您会这样做的主要原因是它允许异步交互。GUI应用程序不会一步一步地直线前进。它必须动态地响应用户的输入。事件是一种伪造多线程应用程序外观的方法。它可以让用户看到许多事情同时发生,而不会相互打断。

    onComputerMove 活动。您可以使用一个函数来处理该事件,该函数获取移动的规范,更新棋盘的视觉表示,并为用户弹出一条消息,然后退出。然后,当玩家移动时,你可以发射 onPlayerMove

        3
  •  1
  •   jturcotte    17 年前

    事件最美妙的地方在于减少了两个模块或类之间的双向显式耦合。

    假设我有两个班:婴儿和妈妈


    • 妈妈叫 baby.pokeBelly() 每半小时给宝宝打一次电话,知道你是否需要打电话 baby.fillWith(milk) .
      问题是,妈妈的线在婴儿出生后必须在一个while循环中等待一整天
    • 宝宝知道它的相关妈妈,并打电话给 mommy.feed(me) 婴儿。装满(牛奶) .
      问题是,让一个简单的婴儿让合适的妈妈填饱肚子。
      婴儿不会这样做,因为他们应该保持简单。

    Mommy.OnBabyCries(baby) baby.Cry

    void Mommy.OnBabyCries(baby) {
        baby.fillWith(milk)
    }
    

    这种逻辑存在于妈妈身上,甚至在以后的任何保姆身上,宝宝都会保持快乐,不必担心。

        4
  •  0
  •   Indeed is Trash    17 年前

    我不知道我是否完全理解你的问题,但一个有事件的类就像一个有按钮的GUI。把它想象成一个人类。..在每个有活动的班级里,都有一个小人物可以按下虚拟按钮。他不知道按钮会做什么,但他知道什么时候按下。现在想象一个相关的类,里面有另一个小人物。那个人知道,当他听到按钮被按下的消息时,他应该做点什么。

    任何时候你想让第二个人知道第一个人做的事情,你都可以在第一类和第二类之间连接交换机(订阅活动)。当第一个人按下按钮(启动事件)时,第二个人会做他知道应该做的任何事情。。。

        5
  •  0
  •   Quassnoi    17 年前

    StackOverflow

    通常,你只写一个 onclick ,更新其中的所有元素,每次页面布局更改时,尽量不要忘记更改它。

    相反,你可以申报 onVoteDown 并订阅此活动:

    • 你的声誉 div
    • img
    • 你的 XmlHTTPRequest 它会将您的投票发送到服务器。
        6
  •  0
  •   Jonathan Lonowski    17 年前

    我不完全确定你想要什么样的答案,所以如果这还不够接近,我很抱歉。 ;)


    靠近 习俗 自定义操作 , 自定义触发器 ,或者说真的

    自定义操作 自定义触发器 将是一个没有语言定义或不易获得的听众。

    如果你正在寻找 ,我真的帮不了你。不过,我认为JavaScript中对它们的支持并不多。


    要定义 行动 ...

    事件通常是通过对象的预定义属性建立的,例如 window.onload 默认情况下,它们都等于 undefined null 因此,要使用它们,你必须将它们设置为函数的值。

    window.onload = function (eventObject) {
        /* ... */
    };
    

    function handleOnload(eventObject) {
        /* ... */
    }
    
    window.onload = handleOnload; /* note the lack of parenthesis */
    

    /* ... */ 将被执行。

    还有更正式的方法可用于创建事件。W3C定义 addEventListener attachEvent . More info .

    有很多参考资料可供学习可用事件列表。这里有两个应该给你一个良好的基础:


    浏览器通常处理事件的触发——无论是浏览器事件还是( onload onclick ).属性和功能旨在响应。

    触发 你自己的活动不是最容易完成的。要完全定义 Event 对象需要一些工作—— varies between browsers .

    对象,您可以简单地调用事件:

    window.onload();