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