责任链模式 模拟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 未阻止事件冒泡

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值