pokemonUI项目——Popover组件的异步操作

188 阅读1分钟

在做pokemonUI项目的popover组件时,需要实现点击出现内容然后点击空白地方可以实现隐藏内容的功能。

初次失败

为了实现这个功能我们有一个初步的想法:

截屏2022-09-17 13.09.49.png 当visible为true时,即内容显示时,我们添加一个事件监听,当我们点击body的部分时,让visible为false来实现隐藏。这时我们发现,刚开启就被关闭了。

解决方案

所以我们使用异步,这里我们先选择nextTick来进行异步操作。 Vue3中 nextTick的使用略有不同 根据Vue3的官方文档可以得知使用方法

<script>
import { nextTick } from 'vue'

export default {
  data() {
    return {
      count: 0
    }
  },
  methods: {
    async increment() {
      this.count++

      // DOM not yet updated
      console.log(document.getElementById('counter').textContent) // 0

      await nextTick()
      // DOM is now updated
      console.log(document.getElementById('counter').textContent) // 1
    }
  }
}
</script>

<template>
  <button id="counter" @click="increment">{{ count }}</button>
</template>

截屏2022-09-17 12.24.00.png

但是我们在通过log调试法的时候发现1和2同时打出,也就是点击之后立即触发了回调,visible马上被设置成了false。于是我们转换一下思路

继续解决

这次我们使用setTimeout

image.png

值得一提的是,这样写忽略了一个问题,我们点击关闭popover是,还需要将click的事件监听移除,否则只能点两次,一直增加事件监听。 再删除的时候,由于我们的事件监听函数是个箭头函数无法指向,我们需要改成具名函数,所以需要在后面bind(this)这样子我们在移除这个函数的时候实际上是移除了x.bind()这个函数。所以需要单独定义一下。

优化结果:

export default {
  name: 'pokemonPopover',

  data() {
    return {visible: false}
  },
  methods: {
    show() {
      this.visible = !this.visible
      if (this.visible === true) {
        setTimeout(() => {
          let eventHandler = () => {
            this.visible = false
            document.removeEventListener('click', eventHandler)
          }
          document.addEventListener('click', eventHandler)
        }, 0)
      }
    }
  }
}