最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

vue3中addEventListener的用法詳解

 更新時間:2023年08月23日 09:32:39   作者:遠山無期  
vue3中定義全局指令時,往往會碰到一個問題:事件無法解綁,為什么會這樣,因為通常在指令的mounted鉤子中綁定事件,事件處理函數(shù)也定義在mounted中,本文講給大家講講vue3中addEventListener的妙用,需要的朋友可以參考下

緣起

vue3中定義全局指令時,往往會碰到一個問題:事件無法解綁。為什么會這樣,因為通常在指令的mounted鉤子中綁定事件,事件處理函數(shù)也定義在mounted中。在指令的unmounted鉤子函數(shù)中無法獲取到定義的事件處理函數(shù),所以綁定的事件無法銷毀,尤其當這個事件是綁定在父組件,或者body上時,無法解綁事件,指令大量使用會造成性能問題。

removeEventListener 方法可以刪除使用 addEventListener 方法添加的事件。使用事件類型,事件偵聽器函數(shù)本身,以及可能影響匹配過程的各種可選擇的選項的組合來標識要刪除的事件偵聽器,簡單說要使用removeEventListener移除事件,需要事件處理函數(shù)和添加時的事件處理函數(shù)是同一個。

如下一個判斷鼠標點擊區(qū)域是否在指定區(qū)域內(nèi)的指令:

// 使用場景:僅在點擊select組件外部區(qū)域,收起下拉選項
import { Directive } from 'vue'
export const clickOutside: Directive = {
  mounted(el: Element, { value }) {
    const controller = new AbortController()
    controllerMap.set(el, controller)
    document.body.addEventListener(
      'click',
      (e) => {
        // 在外部區(qū)域點擊了
        if (!el.contains(e.target as Element)) {
          typeof value === 'function' && value()
        }
      }
    )
  }
}

如上指令,在銷毀時無法進行事件的移除,導致事件處理函數(shù)無法被銷毀,占用內(nèi)存無法釋放:

尋解

查看mdn# addEventListener的解釋,發(fā)現(xiàn)了一個神奇的參數(shù):

  • signal 可選: AbortSignal,該 AbortSignalabort() 方法被調(diào)用時,監(jiān)聽器會被移除。

這不就可以完美解決了么,立馬優(yōu)化指令:

import { Directive } from 'vue'
const controllerMap = new WeakMap<Element, AbortController>()
export const clickOutside: Directive = {
  mounted(el: Element, { value }) {
    const controller = new AbortController()
    controllerMap.set(el, controller)
    document.body.addEventListener(
      'click',
      (e) => {
        // 在外部區(qū)域點擊了
        if (!el.contains(e.target as Element)) {
          typeof value === 'function' && value()
        }
      },
      {
        capture: true, // 為了防止v-if切換導致的判斷誤差,在捕獲階段觸發(fā)事件
        signal: controller.signal
      }
    )
  },
  beforeUnmount(el) {
    const controller = controllerMap.get(el)
    controller?.abort() // 移除事件
  }
}

如上,在指令銷毀時,觸發(fā)beforeUnmount事件,調(diào)用控制對象控制器對象abort方法移除事件

注意:當我們點擊某塊區(qū)域的時候,需要先判斷是否在指定的區(qū)域內(nèi),然后再執(zhí)行相應的邏輯,這時要求判斷是否在區(qū)域內(nèi)的點擊事件,要優(yōu)先執(zhí)行,所以要設置指令的點擊事件在事件捕獲階段觸發(fā), 即:capture: true

場景

如下場景:

<template>
  <div class="edit-cell" v-clickOutside="clickOutside">
    <template v-if="!edit">
      <a-tooltip :title="value" v-if="value.length > 20">
        <div class="text text-ellipsis">
          {{ value || '--' }}
        </div>
      </a-tooltip>
      <div v-else>{{ value || '--' }}</div>
      &nbsp;
      <edit-outlined class="editable-cell-icon icon" @click="enableEdit" />
    </template>
    <template v-else>
      <component
        :is="EditComponent"
        ref="editComponentRef"
        :placeholder="$t('correction.create.modal.form.projectName.err')"
        class="text-edit"
        :maxLength="200"
        @input="change"
        style="height: 60px; resize: none"
        :value="currentValue"
        @pressEnter="pressEnter"
      />
      &nbsp;
      <check-outlined class="editable-cell-icon-check icon" @click="save" />
    </template>
  </div>
</template>
<script lang="ts" setup>
  import { EditOutlined, CheckOutlined } from '@ant-design/icons-vue'
  const props = defineProps({
    value: {
      type: String,
      default: ''
    },
    type: {
      type: String as PropType<'input' | 'textarea'>,
      default: 'input'
    }
  })
  const emits = defineEmits<{
    change: [value: string]
  }>()
  const currentValue = ref<string>('')
  const EditComponent = computed(() =>
    props.type === 'input' ? 'NWInput' : 'ATextarea'
  )
  const edit = ref<boolean>(false)
  const change = ({ target }) => {
    currentValue.value = target?.value ?? ''
  }
  const pressEnter = () => {
    emits('change', currentValue.value)
    edit.value = false
  }
  const save = () => {
    emits('change', currentValue.value)
    edit.value = false
  }
  const editComponentRef = shallowRef()
  const enableEdit = () => {
    currentValue.value = props.value
    edit.value = true
    nextTick(() => {
      editComponentRef.value.focus()
    })
  }
  const clickOutside = () => {
    edit.value = false
  }
</script>
<style lang="less" scoped>
  .edit-cell {
    display: flex;
    justify-content: flex-start;
    align-items: center;
    .text-edit,
    .text {
      flex: 1;
    }
    &:hover {
      .icon {
        visibility: visible;
      }
    }
    .icon {
      visibility: hidden;
    }
  }
  .text-ellipsis {
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
    text-align: left !important;
  }
</style>

另一種思路

可以將處理函數(shù)定義在指令外,所有指令共用同一個處理函數(shù),參數(shù)綁定在處理函數(shù)上,類似vue2中依賴收集時的:Dep.target,將當前處理的watcher存儲在Dep函數(shù)的target屬性中,當然這種方式只適用于串行的場景

到此這篇關于vue3中addEventListener的用法詳解的文章就介紹到這了,更多相關vue3 addEventListener用法內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • Vue零基礎入門之模板語法與數(shù)據(jù)綁定及Object.defineProperty方法詳解

    Vue零基礎入門之模板語法與數(shù)據(jù)綁定及Object.defineProperty方法詳解

    這篇文章主要介紹了Vue初學基礎中的模板語法、數(shù)據(jù)綁定、Object.defineProperty方法等基礎,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2022-09-09
  • vue中使用微信公眾號js-sdk踩坑記錄

    vue中使用微信公眾號js-sdk踩坑記錄

    這篇文章主要介紹了vue中使用微信公眾號js-sdk踩坑記錄,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2019-03-03
  • Vue自定義屬性實例分析

    Vue自定義屬性實例分析

    這篇文章主要介紹了Vue自定義屬性,結(jié)合實例形式分析了vue.js自定義屬性相關原理、實現(xiàn)方法及操作注意事項,需要的朋友可以參考下
    2019-02-02
  • el-table嵌套el-popover處理卡頓的解決

    el-table嵌套el-popover處理卡頓的解決

    本文主要介紹了el-table嵌套el-popover處理卡頓的解決,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2022-05-05
  • 詳解如何在vue+element-ui的項目中封裝dialog組件

    詳解如何在vue+element-ui的項目中封裝dialog組件

    這篇文章主要介紹了詳解如何在vue+element-ui的項目中封裝dialog組件,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-12-12
  • vue中如何通過函數(shù)傳參數(shù)

    vue中如何通過函數(shù)傳參數(shù)

    這篇文章主要介紹了vue中如何通過函數(shù)傳參數(shù)問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-04-04
  • vue實現(xiàn)tab欄點擊高亮效果

    vue實現(xiàn)tab欄點擊高亮效果

    這篇文章主要為大家詳細介紹了vue實現(xiàn)tab欄點擊高亮效果,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-08-08
  • 解決vue.js提交數(shù)組時出現(xiàn)數(shù)組下標的問題

    解決vue.js提交數(shù)組時出現(xiàn)數(shù)組下標的問題

    今天小編就為大家分享一篇解決vue.js提交數(shù)組時出現(xiàn)數(shù)組下標的問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2019-11-11
  • vue 解決IOS10低版本白屏的問題

    vue 解決IOS10低版本白屏的問題

    這篇文章主要介紹了vue 解決IOS10低版本白屏的問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-11-11
  • 3種vue路由傳參的基本模式

    3種vue路由傳參的基本模式

    這篇文章主要為大家詳細介紹了vue路由傳參的3種基本模式,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-02-02

最新評論

新河县| 田阳县| 卢氏县| 铜川市| 榆社县| 万荣县| 历史| 东乡族自治县| 滕州市| 淮北市| 东丰县| 屯留县| 库尔勒市| SHOW| 延安市| 普格县| 金华市| 孟连| 清镇市| 夏邑县| 大连市| 镇雄县| 东山县| 镇安县| 治县。| 时尚| 巩义市| 锡林郭勒盟| 当雄县| 汪清县| 宽甸| 梁山县| 龙胜| 隆回县| 千阳县| 彰化市| 郯城县| 安顺市| 华亭县| 赞皇县| 江源县|