有时候我们需要监听子组件的事件来完成某些操作,但这些组件是有router-view来控制渲染的,此时就需要在router-view上进行事件绑定
我现在需要router-view会渲染detail和table两个组件,现在,我会在table中触发一个事件,表示进入了detail页面,而parent需要接受到这个参数并且传递给headerCard组件
// parent
<script setup lang="ts">
const headerCard = ref();
const enterDetail = (info:any)=>{
headerCard.value.addInfo(info)
}
</script>
<div class="headerBox">
<HeaderCard ref="headerCard" ></HeaderCard>
</div>
<div class="TableBox">
<router-view @enterDetail=enterDetail>
<!-- <table> -->
<!-- <detail> -->
</router-view>
</div>
// table
const emits = defineEmits(['enterDetail'])
const enterDetail = ()=>{
emits('enterDetail', {
name: row.name
})
router.push({
name: 'detail',
query: { id: row.id }
})
}
如果这样直接在router-view上监听,代码是能正常工作的,但会出现警告:
大概意思是``你如果要在组件上监听自定义事件,你需要在子组件中显示的声明这个事件`。我们已经在table中定义了这个事件为什么还有这个警告呢?
因为一旦你进入detail页面,router-view渲染的就是detail组件,detail组件是没有这个事件的,所以会报错。此时就需要使用component去动态的给router-view绑定事件。
// parent
<script setup lang="ts">
/**
* @description: 动态判断当前是否是eventTable组件,来控制是否加上enterdetail事件
* @param {*} routeName 当前路由的name,他的类型是来自RouteRecordNameGeneric类型
* @return {*}
*/
const shouldListenToEvent = (routeName: string | symbol | undefined) => {
return routeName === 'EventTable'
}
</script>
<div class="TableBox">
<router-view v-slot="{ Component, route }">
<!-- 是table组件就去监听enterdetail事件 -->
<component
:is="Component"
v-if="shouldListenToEvent(route.name)"
@enterDetail="enterDetail"
/>
<!-- 如果不是正常渲染其他组件 -->
<component :is="Component" v-else />
</router-view>
</div>
此时,就可以正常的传递数据,并且控制台不会报错了。