【事件监听器】vue3子组件判断父组件是否绑定某emit事件

Child.vue

<script setup lang="ts">
import { getCurrentInstance, defineEmits, onMounted, ref } from 'vue'

const emit = defineEmits(['update'])

// 用来存储父组件是否真正传入了 @update
const hasUpdateListener = ref(false)
onMounted(() => {
  const internal = getCurrentInstance()
  const props = (internal?.vnode.props || {}) as Record<string, any>
  // 事件处理器会被归一化为 onXxx
  hasUpdateListener.value = typeof props.onUpdate === 'function'
})

function clickBtn() {
  if (hasUpdateListener.value) {
    emit('update', '新的内容')
  } else {
    console.warn('[Child] 父组件未绑定 @update,emit 会被忽略')
  }
}
</script>

<template>
  <button @click="clickBtn">
    {{ hasUpdateListener ? '触发 update' : '无 update 监听' }}
  </button>
</template>

Father.vue

<!-- 绑定了update事件 -->
<Child @update="handleUpdate"/>

<!-- 未绑定 -->
<Child/>

使用案例

子组件:点击按钮切换功能的模块,想在切换前增加一个before-change方法,可以控制被切换前的事件。若父组件未绑定@before-change,则默认直接切换(即执行.then()方法)。

SwitchBtn.vue

<script setup lang="ts">
import { ref, onMounted, getCurrentInstance } from 'vue';

defineOptions({
  name: 'SwitchBtn',
});

const emit = defineEmits(['beforeChange']);
const beforeChangeListener = ref(false);
const clickBtn = () => {
  new Promise((resolve, reject) => {
    if (beforeChangeListener.value) {
      emit('beforeChange', (result: boolean) => {
        if (result) {
          resolve(1);
        } else {
          reject(1);
        }
      });
    } else {
      resolve(1);
    }
  })
    .then(() => {
      console.log('切换成功');
    })
    .catch(() => {
      console.log('取消切换');
    })
};
onMounted(() => {
  const internal = getCurrentInstance();
  const props = (internal?.vnode.props || {}) as Record<string, any>;
  beforeChangeListener.value = typeof props.onBeforeChange === 'function';
});
</script>
<template>
    <button @click="clickBtn">切换模式</button>
</template>

使用组件

<script setup>
import SwitchBtnfrom '../language.vue';
import { showConfirmDialog } from 'vant';
import 'vant/lib/dialog/style';

const beforeChange = (cb) => {
  showConfirmDialog({
    title: '切换',
    message: `确定切换模式吗?`,
  })
    .then(() => {
      cb(true);
    })
    .catch(() => {
      cb(false);
    });
};
</script>

<template>
  <SwitchBtn @before-change="beforeChange" />
</template>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值