鸿蒙JS事件冒泡与捕获 原创 精华
介绍
首先在鸿蒙官网HTML语法参考里面有事件冒泡与捕获的介绍,这里我们一起尝试学习下。
为什么想起来介绍这个呢,因为需要实现一个功能一个list列表点击某行左侧标签可以拖动其item,但是拖动时触发了父组件的滚动条滚动事件。
代码尝试冒泡事件与捕获事件
以touch事件为例,鸿蒙将touch事件分成了touchstart、touchmove、touchend三种,我们以touchstart为例。
index.html
<div on:touchstart.capture="capture1" on:touchstart.bubble="bubble1">
<div on:touchstart.capture="capture2" on:touchstart.bubble="bubble2">
<text on:touchstart.capture="capture3" on:touchstart.bubble="bubble3">12222</text>
</div>
</div>
index.js
capture1(){
console.log("testtest++capture1")
},
capture2(){
console.log("testtest++capture2")
},
capture3(){
console.log("testtest++capture3")
},
bubble1(){
console.log("testtest++bubble1")
},
bubble2(){
console.log("testtest++bubble2")
},
bubble3(){
console.log("testtest++bubble3")
}
执行后,log日志为:
[phone] 08/26 19:19:22 23084 [Console DEBUG] app Log: testtest++bubble3
[phone] 08/26 19:19:22 23084 [Console DEBUG] app Log: testtest++bubble2
[phone] 08/26 19:19:22 23084 [Console DEBUG] app Log: testtest++bubble1
换成touchmove、touchend的捕获冒泡也是一样的结果,由此可见至少鸿蒙目前不支持touch捕获事件,冒泡事件是由子元素往父元素冒泡,跟ie、谷歌浏览器走的冒泡事件流一致。
冒泡事件介绍
冒泡事件又分为绑定冒泡事件、绑定并阻止冒泡事件向上冒泡两种。如果不阻止冒泡事件向上冒泡,执行结果如上一节介绍。如果组织冒泡事件呢?
index.html
<div on:touchstart.bubble="bubble1" on:touchmove="touchmove1" on:touchend="touchend1" >
<div on:touchstart.bubble="bubble2" on:touchmove="touchmove2" on:touchend="touchend2" >
<text on:touchstart.bubble="bubble3" grab:touchmove="touchmove3" grab:touchend="touchend3" >12222</text>
</div>
</div>
index.js
bubble1(){
console.log("testtest++touchstart1")
},
bubble2(){
console.log("testtest++touchstart2")
},
bubble3(){
console.log("testtest++touchstart3")
},
touchmove1(){
console.log("testtest++touchmove1")
},
touchmove2(){
console.log("testtest++touchmove2")
},
touchmove3(){
console.log("testtest++touchmove3")
},
touchend1(){
console.log("testtest++touchend1")
},
touchend2(){
console.log("testtest++touchend2")
},
touchend3(){
console.log("testtest++touchend3")
}
执行后,log日志为:
[phone] 08/26 19:35:26 13856 [Console DEBUG] app Log: testtest++touchstart3
[phone] 08/26 19:35:26 13856 [Console DEBUG] app Log: testtest++touchstart2
[phone] 08/26 19:35:26 13856 [Console DEBUG] app Log: testtest++touchstart1
[phone] 08/26 19:35:26 13856 [Console DEBUG] app Log: testtest++touchmove3
[phone] 08/26 19:35:26 13856 [Console DEBUG] app Log: testtest++touchmove2
[phone] 08/26 19:35:26 13856 [Console DEBUG] app Log: testtest++touchmove1
[phone] 08/26 19:35:26 13856 [Console DEBUG] app Log: testtest++touchend3
[phone] 08/26 19:35:26 13856 [Console DEBUG] app Log: testtest++touchend2
[phone] 08/26 19:35:26 13856 [Console DEBUG] app Log: testtest++touchend1
我们修改index.html,阻止第二层touchstart事件向上冒泡。
<div on:touchstart.bubble="bubble1" on:touchmove="touchmove1" on:touchend="touchend1" >
<div grab:touchstart.bubble="bubble2" on:touchmove="touchmove2" on:touchend="touchend2" >
<text on:touchstart.bubble="bubble3" on:touchmove="touchmove3" on:touchend="touchend3" >12222</text>
</div>
</div>
执行后,log日志为:
[phone] 08/26 19:38:12 16396 [Console DEBUG] app Log: testtest++touchstart3
[phone] 08/26 19:38:12 16396 [Console DEBUG] app Log: testtest++touchstart2
[phone] 08/26 19:38:12 16396 [Console DEBUG] app Log: testtest++touchmove3
[phone] 08/26 19:38:12 16396 [Console DEBUG] app Log: testtest++touchmove2
[phone] 08/26 19:38:12 16396 [Console DEBUG] app Log: testtest++touchmove1
[phone] 08/26 19:38:14 16396 [Console DEBUG] app Log: testtest++touchend3
[phone] 08/26 19:38:14 16396 [Console DEBUG] app Log: testtest++touchend2
[phone] 08/26 19:38:14 16396 [Console DEBUG] app Log: testtest++touchend1
执行结果发现touchstart并不会向父组件冒泡了,但是不影响touchmove、touchend事件,这个跟android有点区别。有了这个基础,下面我们介绍下开头遇到的问题,子层拖动影响滚动条事件处理。
实现效果
实现方式
index.css
.container {
flex-direction: column;
}
index.html,注意这里的样式最好写进css文件中,这里为了图测试方便直接写在了html中。
<div class="container" >
<div style="height: 300px;width:100%;background-color: gray;"></div>
<div id="mydiv" style="height: 900px;width:100%;background-color: gray;" >
<div style="position: absolute;top: {{top}}px;background-color: blue;height: 40px;">
<div >
<text style="color: white;"
grab:touchmove.bubble="grabtouchmove"
on:touchstart.bubble="touchstart" on:touchmove.bubble="touchmove" on:touchend.bubble="touchend" >拖动</text>
</div>
<text style="margin-left: 30px;color: white;" >标题</text>
</div>
<div style="position: absolute;top: 40px;background-color: blue;height: 40px;" >
<text style="color: white;" >拖动</text>
<text style="margin-left: 30px;color: white;" >标题</text>
</div>
<div style="position: absolute;top: 80px;background-color: blue;height: 40px;" >
<text style="color: white;">拖动</text>
<text style="margin-left: 30px;color: white;" >标题</text>
</div>
<div style="position: absolute;top: 120px;background-color: blue;height: 40px;" >
<text style="color: white;">拖动</text>
<text style="margin-left: 30px;color: white;" >标题</text>
</div>
<div style="position: absolute;top: 160px;background-color: blue;height: 40px;" >
<text style="color: white;">拖动</text>
<text style="margin-left: 30px;color: white;" onclick="myclick" >标题</text>
</div>
</div>
</div>
index.js
export default {
data: {
top:0,
globalY:0
},
onInit(){
},
touchstart(e){
console.log("test:touchstart"+e.touches[0].globalY);
this.globalY = e.touches[0].globalY;
console.log("test:touchstart-globalY="+this.globalY)
},
touchmove(e){
console.log("test:touchmove"+e.touches[0].globalY);
this.top = (e.touches[0].globalY-this.globalY);
console.log("test:touchmove-top="+this.top)
},
touchend(e){
// console.log("test:touchend"+JSON.stringify(e));
this.top = 0;
console.log("test:touchend-top="+this.top)
},
grabtouchmove(){
}
}
这里需要注意的是grab:touchmove.bubble方法赋值了一个空方法,on:touchmove.bubble这个是真正拖动处理的方法。原来的做法是grab:touchmove.bubble直接赋值拖动处理方法,on:touchmove.bubble并未赋值任何代码,具体代码如下:
<text style="color: white;"
on:touchstart.bubble="touchstart" grab:touchmove.bubble="touchmove"
on:touchend.bubble="touchend" >拖动</text>
上面这种代码拖动并无任何作用,所以可能是我对”绑定并阻止冒泡事件向上冒泡“这个说法理解有误。
总结
使用的时候on:{event}.bubble、grab:{event}.bubble需要分开处理,这个目前api6版本尝试的结果,项目功能得已解决,后期api是否有变动,我们还需要持续学习关注。