鸿蒙JS事件冒泡与捕获 原创 精华

cqyin
发布于 2021-8-27 17:52
浏览
1收藏

介绍

首先在鸿蒙官网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有点区别。有了这个基础,下面我们介绍下开头遇到的问题,子层拖动影响滚动条事件处理。

实现效果

鸿蒙JS事件冒泡与捕获-鸿蒙开发者社区

实现方式

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是否有变动,我们还需要持续学习关注。

©著作权归作者所有,如需转载,请注明出处,否则将追究法律责任
分类
已于2021-8-27 17:52:20修改
2
收藏 1
回复
举报
回复
    相关推荐