zoukankan      html  css  js  c++  java
  • flex>事件 小强斋

    Flex事件概述

    Flash/Flex中的事件是编写应用的基础,是和用户交互的基础。应用和用户之间的交互就是以事件为桥梁。

    应用对用户动作的响应相当于应用和外界的交互,而应用之间也有需要响应的事情,这相当于内部的交互。举个例子来说,用户单击了某个按钮,程序就应该做某些事情,这就是用户和外界的交互;而应用中某个数据的改变,应用其他部分也要随其做相应的改变就是内部交互。

    Flex事件机制

    1.什么是事件机制
    事件可以看作是一种触发机制,当满足了一定的条件后,会触发这个事件。比如MouseEvent就是指的当鼠标进行操作之后触发的一系列的事件。很多控件中都有click事件,这个事件就是一个MouseEvent的实例,当点击鼠标后,系统会自动抛出一个名称为click的MouseEvent事件。如果此时在click上注册一个方法,那么触发该事件时就会执行这个方法。

    事件的机制包括注册事件、触发事件、事件的传递

    事件注册:指将事件的处理函数指定给对象的一个事件,实际上是对该事件创建一个侦听器。事件被注册后,当事件发生后,就会调用注册的事件响应函数。

    事件触发:注册到对象上的事件发生时,就是事件的触发。事件触发后会调用注册在该事件上的事件响应函数,同时创建事件对象的一个实例,该实例会包含事件的信息。一个事件的信息包括以下几种:

    1)属性bubbles:布尔类型,显示该事件是否为冒泡事件;

    2)属性cancelable:布尔类型,显示是否可以阻止与事件相关联的行为;

    3)对象currentTarget:与当前事件相关联的对象。

    4)属性eventPhase:无符号整数,指示当前事件在整个事件流中的阶段;

    5)对象Target:触发事件的对象。也就是整个事件流的源头。在实际过程中使用currentTarget来处理事件的当前目标;

    6)字符串type:当前事件的类型。如事件是click,那这个值就是click。

    一个事件被触发后,一般经历3个阶段,第一阶段就是捕获阶段,Flex应用是一层一层的关系,比如顶级Application里面有一个容器Canvas,而Canvas里面有一个VBox,真正发生事件的是VBox里的一个按钮。当用户单击这个按钮时,实际上该事件会经历3个对象,第一个就是Application,第二个就是Canvas,第三个是VBox,最后才是事件注册的对象按钮。Click事件自上而下的进行查找点击对象的工作,这个过程就是捕获阶段。第二个阶段是目标锁定阶段,当自上而下找到事件注册并触发的对象时,Flex将会自动创建一个Event的实例。这个实例包括整个事件的相关信息。第三个阶段就是冒泡阶段,与前面捕获阶段相反冒泡阶段就是时间会向上一级传递。

    事件传递:对于处理时间来说,事件的传递是关键。一个事件被触发后,事件就开始冒泡,形成了一个事件流。

    Flex事件分发

    最终继承自EventDispatcher的对象都会含有dispatchEvent这个方法,他有一个参数,事件对象。之前说到的事件注册通道,他只是一个通道,实际上事件是由这个方法来分发出去的,通道只是一个管道而已。他的作用就是分发一个事件对象,他的分发是没有目的的,一种广播形式的,Flex的事件监听线程会接收到各种各样的事件(我们称之为捕获事件,这在后面会介绍到),那么哪种才是你要的事件,标识就通过事件的type属性来区分。

    1)Flex事件对象

    在分发事件时,将会分发一个事件对象出去。不管是那个事件类,都是继承自flash.events.Event对象的,他包含一些比较重要的属性,type和bubbles。
    type是事件的类型,事件监听通过这个参数来识别是否是自己所监听的事件。
    bubbles是个布尔值,决定了该对象是否会向上传递。默认是false。什么意思呢,
    比如说,当button组件分发click事件对象时,设置的bubbles为false,
    dispatchEvent(newMouseEvent(“click”,false));
    事件对象无法跨越组件本身,当然,除了之前讲到的注册通道(这样就很形象了吧)因此,如果没有注册通道,在Flex主应用中,就无法捕获到这个button组件分发出的事件。如果我们将Bubbles设为true,
    这个事件可以跨过组件本身,到达Flex主应用里。不止这样,在帮助手册中明确说到,如果在传递过程中间一直没有被捕获的话,这个事件会逐层上传,直到最终的stage,那时如果还没被捕获,这个事件就会被销毁掉。这样一来,即使我们没有click的事件通道,只要我们在Flex主应用中添加Flex事件监听器(addEventListener)那么我们就可以获得到这个分发出的click事件了。

    一、事件注册通道
    通道是只能在mxml的代码提示中可以看到的,他的作用就是给mxml组件提供 事件触发时所执行的方法的注册通道,而且能在代码提示中可见,这样给组件提供了很大的抽象的好处,我们可以很清楚的告诉组件的使用者,组件里包含哪些事件给你调用。
    Button的click事件是继承自核心类InteractiveObject,遗憾我们看不到他的源码,但是说明了“事件注册通道”是可以继承的。我们会在自定义事件中讲述到如何声明“事件注册通道”。


    该示意图对应的Flex主应用的mxml代码

    <mx:Script>
              <![CDATA[
                    import mx.controls.Alert;        
                    private function clickHandler(e:MouseEvent){
                          Alert.show(e.currentTarget.toString());
                    }
              ]]>
    </mx:Script>
    <mx:Button id="testBtn" click="clickHandler(event)" label="测试">
    </mx:Button>

    1、设计视图下图所示,拖一个Panel、一个Textarea、两个按钮到设计界面。

    2、源代码如下所示:

    <?xml version="1.0" encoding="utf-8"?>
     <s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
     xmlns:s="library://ns.adobe.com/flex/spark"
     xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600"
     creationComplete="init()">
    
     <fx:Script>
     <![CDATA[
     import mx.utils.OnDemandEventDispatcher;
     import spark.components.TextArea; 
    private function recordEvent(e:Event):void
     {
     writeLog(e.target.id + "被点击," + "当前对象" + e.currentTarget.id);
     e.stopPropagation();
     }
     private function writeLog(str:String):void
     {
     ta.text += str + "\n";
     }
     private function clear(e:Event):void
     {
     e.stopPropagation();
     ta.text = "";
     } 
    ]]>
     </fx:Script>
    
     <fx:Declarations>
     <!-- 将非可视元素(例如服务、值对象)放在此处 -->
     </fx:Declarations>
     <s:Panel width="204" height="231" click="recordEvent(event)" id="panel" x="15" y="15" title="事件触发与传递" fontSize="12">
     <s:TextArea x="17" y="7" id="ta" width="170"/>
     <s:Button x="17" y="164" label="点击" id="btn" click="recordEvent(event)"/>
     <s:Button x="117" y="164" label="清空" click="clear(event)"/>
     </s:Panel>
    
    </s:Application>
    

    3、编译运行,结果截图如下:

    二、事件监听

    在分发中,我们讲到,如果不是通过注册通道来调用触发事件,那么我们是需要一个监听来捕捉的。如何捕捉到分发出的事件,就是通过事件的type值。

    <mx:Application xmlns:mx=http://www.adobe.com/2006/mxml layout="absolute" xmlns:comp
          creationComplete='init()'
    > 
    <mx:Script>
                    <![CDATA[
    private function init(){
                        testBtn.addEventListener(“click”, clickHandler);
    }

    Flex的事件中都提供了一些静态常量,让我们调用,避免我们打错了。因此这句话可以这么写
    testBtn.addEventListener(MouseEvent.CLICK,clickHandler);
    我们看到,监听的回调方法中没有传递参数,是的,这和通道的写法有些不同,这里的回调方法(即clickHandler)只是个引用,并不是代表方法的执行,他的含义是,告诉eventLinstener,如果捕捉到click事件,那么就去找clickHandler,并执行它,event对象参数在执行时动态的传递。

    三.绑定机制

     在我们了解了事件机制后,那么理解绑定就不难了。绑定其实也是事件机制的运用
    1.  什么是绑定
    绑定的原理就是事件,在被绑定的对象上增加了改变事件的监听,一旦某个被绑定对象改变后,就会分发一个“propertyChange”事件(默认的,也可以改变成自己定义的事件),在其他组件中,会有propertyChange的事件监听,当捕捉到该事件后,则会去更新组件的属性并显示。
    绑定的作用在于,将Flex中的变量、类、方法等与组件的值进行绑定。例如,一个变量如果被绑定后,那么引用该变量的组件的相关属性也会发生改变。我们用一个实例来表示

    <?xml version="1.0" encoding="utf-8"?>
    <mx:Application xmlns:mx=http://www.adobe.com/2006/mxml layout="absolute" xmlns:comp
          >
          <mx:Script>
              <![CDATA[
                    import mx.controls.Alert;            
                    [Bindable]
                    private var isSelected:Boolean;
                    private function clickHandler(e:MouseEvent){
                    //Alert.show(e.currentTarget.toString());
    isSelected=isSelected?false:true; //这句话的意思是如果isSelected为true,改变它为false,如果它为false,改变它为true;
                          Alert.show(isSelected.toString());
                    }
              ]]>
          </mx:Script>
          <mx:Button id="testBtn"  click="clickHandler(event)" label="测试" />
          <mx:CheckBox x="60" selected="{isSelected}" />
    </mx:Application>

    上述程序的效果就是,当点击button时,button不是直接改变checkbox的选中状态,而是改变isSelected这个变量,由于isSelected是被绑定了的,那么会关联的改变CheckBox的选中状态。
    这样看起来有些多此一举,完全可以直接改变checkbox的selected属性,我只是为了演示一下效果。如果说你的checkbox是动态构造的上百个,你不会去一个个的改变他吧。
    如果这个代码中取消了[Bindable]的声明,会怎么样?isSelected不会改变了吗?
    isSelected会改变,我们alert出来的结果也会显示结果改变了,但是checkbox的选择状态不会改变,因为当一个组件由创建到最终显示出来时是经过很多方法的,比如addChild,commitProperties,updateDisplayList等,updataDisplayList则是类似刷新显示效果一样的方法。
    仅仅改变属性,而不去更新显示效果那么组件不会因为属性的改变而发生任何变化。
      绑定的原理也是利用的事件分发。


    四.  自定义事件的分发

    1.  自定义事件 components/MyEventTest.as

    package components
    {
          import mx.events.FlexEvent;
          public class MyEventTest extends FlexEvent
          {
              public static const ONCHANGE:String = "onChange";
              public var eventInfo:String; //自定义的事件信息
              public function  MyEventTest(s:String){
                    super(s); //如果在构造时不设bubbles,默认是false,也就是不能传递的。
                    eventInfo="这个事件是:"+s;
              }
          }
    }
    
              

    2.        自定义组件 components/ComponentForEvent.as

    package components
    {
          import flash.events.EventDispatcher;
          //这个就是声明事件注册通道的方法了。name是事件对应的名称,也就是之前提到的type。Type是该事件的类
          [Event(name="onChange", type="components.MyEventTest")]
          public class ComponentForEvent extends EventDispatcher
          {
              private var name:String;
              public function changeName(newName:String){
                    this.name=newName;
                    dispatchEvent(new MyEventTest(MyEventTest.ONCHANGE) );
              }
          }
    }

    3.        App.mxml

    <?xml version="1.0" encoding="utf-8"?>
    <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" xmlns:comp
    > 
    <mx:Script>
    <![CDATA[
    import mx.controls.Alert;
    private function  changeName(){
                        cfe.changeName("新名称");
    }
                    ]]>
    </mx:Script>
    <mx:Button id="testBtn"  click=" changeName ()" label="测试" />
    <components:ComponentForEvent
    id="cfe"  />
    </mx:Application>



     

  • 相关阅读:
    5.scala中的对象
    4.scala中的类
    第八章 前端框架
    第六章 用户管理
    第五章 权限验证
    第四章 功能初始化
    第三章 项目结构
    第二章 基于二进制进行权限管理的理论知识
    第一章 权限管理DEMO简介
    NopCommerce源代码分析之用户验证和权限管理
  • 原文地址:https://www.cnblogs.com/xiaoqiangzhaitai/p/5637555.html
Copyright © 2011-2022 走看看