[ Vue ] 給 slot 插槽綁定事件

最近寫了一個下拉組件,希望任意形式的觸發源點擊都可以展開這個組件。

最終效果圖如下:

方案一:slot-scope 傳方法

<!-- 僞代碼:下拉框組件 -->

<template>
    <slot change-display="changeDisplay"></slot>
    <div v-show="mVisiable">*下拉框代碼省略*<div>
<template>

<script>
export default {
    data(){
        return {
            mVisiable: false
        }
    }

    methods:{
        changeDisplay(){
            this.mVisiable = !this.mVisiable
        }
    }
}
</script>
<!--使用下拉彈窗組件-->
<dropdown v-model="value" :list="list">
      <button slot-scope="{changeDisplay}" 
        @click="changeDisplay">{{value}}</button>
</dropdown>

不過這就導致每次用插槽都要寫 slot-scope 去取修改顯示狀態的函數。

方案二:找 VNode 中對應的頁面元素

插曲:

<!-- 僞代碼:下拉框組件 -->
<template>
    <slot></slot>
    <div v-show="mVisiable">*下拉框代碼省略*<div>
<template>

<script>
export default {
    data(){
        return {
            mVisiable: false
        }
    }

    methods:{
        changeDisplay(){
            this.mVisiable = !this.mVisiable
        }
    }

    mounted() {
      console.log(this.$slots)
    }
}
</script>


<!--使用下拉彈窗組件-->
<dropdown v-model="value" :list="list">
  <template v-slot>
    <button>{{value}}</button>
  </template>
</dropdown>

根據vue文檔 slot 被廢棄了(但還是兼容的)使用 v-slot 指定插槽,但是輸出VNode 中的 elm 是 undefined。

然後去查找 github vue issues 找到如下回答, 傳送門: issue

最後換回舊的插槽方法

<!--使用下拉彈窗組件-->
<dropdown v-model="value" :list="list">
    <button>{{value}}</button>
</dropdown>

此時得到了插槽內的元素


修改下拉組件。爲VNode中的elm增加點擊事件。

<!-- 僞代碼:下拉框組件 -->
<template>
    <slot></slot>
    <div v-show="mVisiable">*下拉框代碼省略*<div>
<template>

<script>
export default {
    data(){
        return {
            mVisiable: false
            reference: undefined
        }
    }

    methods:{
        changeDisplay(){
            this.mVisiable = !this.mVisiable
        }
    }

    mounted() {
        if (this.$slots.default) {
          this.reference = this.$slots.default[0].elm
        }
        if (this.reference) {
          this.reference.addEventListener('click', this.changeVisiable, false)
        }
    }

    beforeDestroy() {
        if (this.reference) {
          this.reference.removeEventListener('click', this.changeVisiable, false)
        }
    }
}
</script>

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章