likes
comments
collection
share

addEventListener的默认事件满足不了我了⚡,了解下自定义事件吧

作者站长头像
站长
· 阅读数 18

前言

之前在上家公司用vue + element UI技术栈的时候,总是感觉到达自己的舒适区了,工作没什么难度~~~ 直到我遇到了select组件下拉框在滚动页面关不掉的情况,并且,我开始对细节下手想解决这个问题。

然后,我就一路追踪,翻element UI的源码,直接找到了v-clickoutside="handleClose"。感兴趣的小伙伴可以在源码里全局搜索这个关键字。

大致思路: 自定义指令的逻辑中,在整个文档注册了mousedownmouseup事件, mouseup触发时会执行createDocumentHandler函数判断当前DOM是不是select相关的节点,如果不是就执行handleClose关闭弹窗。

最后在滚动事件触发时执行document.dispatchEvent(new Event("mouseup", { bubbles: true })); 解决了这个问题。

那个时候就准备把笔记整理一下,但是一直没时间~~~

最近这家公司在uniapp的开发中又碰到了使用document.dispatchEvent(new Event("自定义事件"))的场景。

这次把这两个案例都在此处整理了一下,给小伙伴们参考一下。

addEventListener的默认事件满足不了我了⚡,了解下自定义事件吧

正文

new Event使用方法介绍

new Event('事件类型', 可选对象);

1, 官网中的可选对象介绍:

  • "bubbles",可选,Boolean类型,默认值为 false,表示该事件是否冒泡。
  • "cancelable",可选,Boolean类型,默认值为 false,表示该事件能否被取消。
  • "composed",可选,Boolean类型,默认值为 false,指示事件是否会在影子 DOM 根节点之外触发侦听器。

2, 案例:

注册一个testEvent自定义事件

window.addEventListener("testEvent", (e) => {
    console.log(e);
});

通过dispatchEvent触发自定义事件,并且给testEvent事件设为可冒泡

 window.dispatchEvent(new Event("testEvent", { bubbles: true }));

addEventListener的默认事件满足不了我了⚡,了解下自定义事件吧

3, 鼠标按下事件默认的禁止冒泡改为允许冒泡

window.addEventListener("mousedown", (e) => {
   console.log(e);
});

window.dispatchEvent(new Event("mousedown", { bubbles: true }));

addEventListener的默认事件满足不了我了⚡,了解下自定义事件吧

4, 场景:

addEventListener的默认事件满足不了我了⚡,了解下自定义事件吧

小伙伴在使用element UI时,肯定遇到过上图的问题。在使用select组件时,经常会遇到下拉框关不掉。

其实是因为隐藏逻辑的是在mouseup事件里写的, 而在移动滚动条的时候并没有触发mouseup事件。

所以通过进行滚动等事件的时候触发mouseup事件就行啦

重新注册鼠标点击离开事件

const MousedownEvent = new Event('mousedown', { bubbles: true })

const MouseupEvent = new Event('mouseup', { bubbles: true })

触发自定义事件

document.dispatchEvent(MousedownEvent)

document.dispatchEvent(MouseupEvent)

new CustomEvent使用方法介绍

它可以传递一些自定义的数据,然后在监听时间的回调函数中接收。

1, 案例:


<div onClick="btnTest('开始')">测试点击区域</div>
    <script>
      function btnTest(e) {
        console.log(e);
        console.log(window);
        window.dispatchEvent(
          new CustomEvent("testOne", {
            detail: "自定义事件传的数据",
          })
        );
      }
      window.addEventListener("testOne", (e) => {
        // 此处接收上面传递的 '自定义事件传的数据'
        console.log(e);
      });

addEventListener的默认事件满足不了我了⚡,了解下自定义事件吧

2, 场景:

PS: 下文内容过多,没遇到下面这个场景的小伙伴,学习到此结束啦。可以先收藏,下次遇到这个场景再来看。

通过 new CustomEvent 进行uniapp转的APP端APP端内嵌的H5端 两者的数据通信

具体思路如下(uniapp中的实现):

  • H5端全局封装通信函数(监听自定义事件+发送事件名给APP)

  • H5端任意页面调用通信函数得到APP端的回参进行自定义逻辑

  • APP端通过webview组件中的@message接口接收H5端传过来的数据

  • APP端通过this.wv.evalJS触发H5端封装的dispatchJS,携带APP中的数据

  • H5端通过dispatchJS触发自定义事件并携带参数,参数在第二步通过APP端的回参获得

2.1, H5端核心代码

通信函数

  • 全局监听自定义事件,通过回参接收APP端传过来的数据

  • 通过uni.postMessage把自定义事件名给到APP端

const useFn = (params) =>
  new Promise((resolve) => {
    const { action, payload } = params
    const Handle = function (event) {
      resolve(event.detail)
      window.removeEventListener(action, Handle)
    }
    window.addEventListener(action, Handle)
    console.log(action, payload)
    uni.postMessage({
      data: {
        action,
        payload,
      },
    })
  })
  
 function getAppEnvUrl() {
  return useFn({
    action: 'get_app_envurl',
    payload: {},
  })
}

export default {
getAppEnvUrl
}

dispatchJS函数(index.html里)

function dispatchJS(eventname, data) {
        window.dispatchEvent(
          new CustomEvent(eventname, {
            detail: data,
          })
        )
      }
2.2, APP端核心代码
<template>
  <view>
    <web-view
      :webview-styles="webviewStyles"
      :src="url"
      @message="getMessage"
    ></web-view>
  </view>
</template>

<script>
  import store from '@/store'

  export default {
    data() {
      return {
        // 加载webview进度条颜色
        webviewStyles: {
          progress: {
            color: '#FEE039'
          }
        },
        url: '', // 网络路径
        wv: null
      }
    },
    methods: {
      getMessage(e) {
        if (e.detail && e.detail.data && e.detail.data.length > 0) {
         this.presets(message)
        }
      },
      presets(message) {
        // 加载完webview
        const webviewReady = () => {
          this.wv = this.$scope.$getAppWebview().children()[0]
        }
       

        const getAppEnvUrl = () => {
          const params = {
            envUrl: this.$store.getters.envUrl
          }
          this.wv.evalJS(
            `dispatchJS('${message.action}', ${JSON.stringify(params)})`
          )
        }

        getAppEnvUrl()
      }
    }
  }
</script>

<style lang="scss" scoped></style>

总结

本文主要介绍了new Eventnew CustomEvent的使用方法和各自在项目中应用的案例。

细节一般是被忽略的,但是成长也是从抓住细节开始。

这篇文章的来源就是死扣细节,然后不断破案,学习总结出来的。

完结

这篇文章我尽力把我的笔记和想法放到这了,希望对小伙伴有帮助。

欢迎转载,但请注明来源。 最后,希望小伙伴们给我个免费的点赞,祝大家心想事成,平安喜乐。

addEventListener的默认事件满足不了我了⚡,了解下自定义事件吧