在责任链模式里,很多对象由每一个对象对其下家的引用而连接起来形成一条链。请求在这个链上传递,直到链上的某一个对象决定处理此请求,并且终止传递。
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 未阻止事件冒泡