当前位置: 代码迷 >> JavaScript >> 责任链形式 模拟javascript事件冒泡
  详细解决方案

责任链形式 模拟javascript事件冒泡

热度:127   发布时间:2012-11-16 14:12:14.0
责任链模式 模拟javascript事件冒泡

在责任链模式里,很多对象由每一个对象对其下家的引用而连接起来形成一条链。请求在这个链上传递,直到链上的某一个对象决定处理此请求,并且终止传递。

javascript事件冒泡:

IE 事件由最接近事件发生坐标的html元素处发起,在事件没有被阻止的情况下,事件将跟随着该界定继承自的各个父节点冒泡穿过整个DOM节点层次

? ? ? ? FF 首先会来一个与IE相反方向的事件流,若未被catch,然后再来一个与IE相同的方向的事件流。

?

由上面可以看出事件冒泡视乎就是责任链模式的一种表现,所以做了如下的代码测试,

1. 对链上的每个元素抽象出一个接口:

?

package com.sail.utils.htmlEventFlow.dom;

import com.sail.utils.htmlEventFlow.event.JsEvent;

/**
 * 所有dom元素的接口
 * @author wjs
 *
 */
public interface Dom {

	//获取当前dom元素的名称
	String getTagName();
	
	//获取其父dom元素
	Dom getParent();
	
	//事件冒泡
	void flowEvent(JsEvent event, Dom dom);
	
	//事件处理
	void catchEvent(JsEvent event);
	
	//阻止冒泡
	boolean stopEvent();
}

?2. 生成一个通用的HTML类型Dom的模板抽象父类

?

package com.sail.utils.htmlEventFlow.dom;

import com.sail.utils.htmlEventFlow.event.JsEvent;

/**
 * HTML类型Dom模板
 * @author wjs
 *
 */
public abstract class DomHtml implements Dom {
	
	//html元素ID
	private String id;
	//html元素名称
	private String tagName;
	//html元素js处理方法
	private String eventFuntion="";

	/**
	 * 冒泡
	 * @event 事件
	 * @dom dom元素集合容器的元素
	 */
	public void flowEvent(JsEvent event, Dom dom) {
		//正向冒泡
		System.out.println(this.getTagName()+" 进行了 "+event.getType());
		//执行事件的方法
		this.catchEvent(event);
		//是否停止冒泡
		if(stopEvent())
			return ;
		//调用dom的
		dom.flowEvent(event, this);
		
		//反向冒泡,事件流
		System.out.println(this.getTagName()+" 进行了 "+event.getType()+"的事件流");
		this.catchEvent(event);
		if(stopEvent())
			return ;
	}

	public abstract Dom getParent() ;
	
	/**
	 * 模板默认处理方法
	 */
	public void catchEvent(JsEvent event) {
		if(this.eventFuntion==null || this.eventFuntion.trim().equals(""))
			System.out.println(this.getTagName()+" 未对事件 "+event.getType()+" 进行处理!");
		else{
			System.out.println(this.getTagName()+" 对事件 "+event.getType()+" 进行如下处理:");
			System.out.println(this.eventFuntion);
			System.out.println("------------------------处理结束--------------------");
		}
	}

	/**
	 * 停止冒泡
	 */
	public boolean stopEvent() {
		if(this.eventFuntion!=null && this.eventFuntion.indexOf("stopPropagation()")!=-1){
			System.out.println("--------------停止往上冒泡啦--------");
			return true;
		}
		System.out.println(this.getTagName()+" 未阻止事件冒泡");
		return false;
	}
	
	public String getEventFuntion() {
		return eventFuntion;
	}

	public void setEventFuntion(String eventFuntion) {
		this.eventFuntion = eventFuntion;
	}

	public String getId() {
		return id;
	}

	public void setId(String id) {
		this.id = id;
	}

	public void setTagName(String tagName) {
		this.tagName = tagName;
	}
	
	public String getTagName(){
		return this.tagName;
	}

}

?4. 生成各种html元素

?

package com.sail.utils.htmlEventFlow.dom;

public class Html extends DomHtml {
	@Override
	public Dom getParent() {
		// TODO Auto-generated method stub
		return null;
	}
}


class Body extends DomHtml {
	@Override
	public Dom getParent() {
		// TODO Auto-generated method stub
		return null;
	}
}

class Table extends DomHtml {
	@Override
	public Dom getParent() {
		// TODO Auto-generated method stub
		return null;
	}
}

class Tr extends DomHtml {
	@Override
	public Dom getParent() {
		// TODO Auto-generated method stub
		return null;
	}
}

class Td extends DomHtml {

	@Override
	public Dom getParent() {
		// TODO Auto-generated method stub
		return null;
	}
}

class Div extends DomHtml {
	@Override
	public void catchEvent(JsEvent event) {
		System.out.println("--------------div通用事件处理方法-------------------");
		System.out.println(this.getTagName()+" 对事件 "+event.getType()+" 进行如下处理 :");
		System.out.println("弹出窗口");
		System.out.println("--------------处理结束-------------------");
	}
	public Dom getParent() {
		return null;
	}
}

class Input extends DomHtml {
	@Override
	public Dom getParent() {
		// TODO Auto-generated method stub
		return null;
	}
}

?5. 生成dom元素容器对象

?

package com.sail.utils.htmlEventFlow.dom;

import java.util.ArrayList;
import java.util.List;

import com.sail.utils.htmlEventFlow.event.JsEvent;
/**
 * dom元素集合容器 同时自己也是个dom元素
 * @author wjs
 *
 */
public class Window extends DomHtml {

	//dom元素集合容器
	List<Dom> elements=new ArrayList<Dom>();
	
	/**
	 * 获取下一个dom元素
	 * @param dom
	 * @return
	 */
	public Dom nextDom(Dom dom) {
		if(dom == null)
			return null;
		int index=elements.indexOf(dom);
		index++;
		if(index <0 || index>=elements.size())
			return null;
		return elements.get(index);
	}
	
	/**
	 * 注册
	 * @param dom
	 */
	public void putDom(Dom dom){
		if(dom==null)
			return ;
		this.elements.add(dom);
	}
	
	/**
	 * 获取目标dom元素的下一个元素,并调用下一个元素的冒泡事件方法
	 */
	@Override
	public void flowEvent(JsEvent event, Dom dom) {
		Dom next=this.nextDom(dom);
		if(next==null){
			System.out.println("事件已经冒到window上了");
			System.out.println();
			return ;
		}
		//在下一个对象的dom对象方法中将“this”传递过去,是为了下一个对象还能回到这个方法
		next.flowEvent(event, this);
	}

	@Override
	public Dom getParent() {
		// TODO Auto-generated method stub
		return null;
	}
}

?6.定义事件接口

?

package com.sail.utils.htmlEventFlow.event;

import com.sail.utils.htmlEventFlow.dom.Dom;

/**
 * 通用事件接口
 * @author wjs
 *
 */
public interface JsEvent {

	//事件类型
	String getType();
	
	//事件作用对象
	Dom getTarget();
	
	//阻止事件冒泡
	void stopPropagation();
}

7.定义点击事件

package com.sail.utils.htmlEventFlow.event;

import com.sail.utils.htmlEventFlow.dom.Dom;

public class ClickEvent implements JsEvent {
	
	private String type;

	public Dom getTarget() {
		return null;
	}

	public String getType() {
		return this.type;
	}
	
	public void setType(String type) {
		this.type=type;
	}

	public void stopPropagation() {

	}

}?

??8.测试代码

?

package com.sail.utils.htmlEventFlow;

import com.sail.utils.htmlEventFlow.dom.*;
import com.sail.utils.htmlEventFlow.event.ClickEvent;


public class FlowEvent {

	public static void main(String[] args) {
		DomHtml input=new Input();
		input.setTagName("input");
		DomHtml div=new Div();
		div.setTagName("div");
		DomHtml td=new Td();
		td.setTagName("td");
		DomHtml tr=new Tr();
		tr.setTagName("tr");
		DomHtml table=new Table();
		table.setTagName("table");
		DomHtml body=new Body();
		body.setTagName("body");
		DomHtml html=new Html();
		html.setTagName("html");
		Window window=new Window();
		window.setTagName("window");
		String function="alert('你好啊')";
		table.setEventFuntion(function);
		
		window.putDom(window);
		window.putDom(input);
		window.putDom(div);
		window.putDom(td);
		window.putDom(tr);
		window.putDom(table);
		window.putDom(body);
		window.putDom(html);
		
		ClickEvent event=new ClickEvent();
		event.setType("click");
		
		window.flowEvent(event, window);
	}
}

?9.运行结果

?

input 进行了 click

input 未对事件 click 进行处理!

input 未阻止事件冒泡

div 进行了 click

--------------div通用事件处理方法-------------------

div 对事件 click 进行如下处理 :

弹出窗口

--------------处理结束-------------------

div 未阻止事件冒泡

td 进行了 click

td 未对事件 click 进行处理!

td 未阻止事件冒泡

tr 进行了 click

tr 未对事件 click 进行处理!

tr 未阻止事件冒泡

table 进行了 click

table 对事件 click 进行如下处理:

alert('你好啊')

------------------------处理结束--------------------

table 未阻止事件冒泡

body 进行了 click

body 未对事件 click 进行处理!

body 未阻止事件冒泡

html 进行了 click

html 未对事件 click 进行处理!

html 未阻止事件冒泡

事件已经冒到window上了

?

如下是dom反向冒js事件

?

html 进行了 click的事件流

html 未对事件 click 进行处理!

html 未阻止事件冒泡

body 进行了 click的事件流

body 未对事件 click 进行处理!

body 未阻止事件冒泡

table 进行了 click的事件流

table 对事件 click 进行如下处理:

alert('你好啊')

------------------------处理结束--------------------

table 未阻止事件冒泡

tr 进行了 click的事件流

tr 未对事件 click 进行处理!

tr 未阻止事件冒泡

td 进行了 click的事件流

td 未对事件 click 进行处理!

td 未阻止事件冒泡

div 进行了 click的事件流

--------------div通用事件处理方法-------------------

div 对事件 click 进行如下处理 :

弹出窗口

--------------处理结束-------------------

div 未阻止事件冒泡

input 进行了 click的事件流

input 未对事件 click 进行处理!

input 未阻止事件冒泡

  相关解决方案