分析Vben代码时发现,其项目中存在:props传值如onXxx,在调用子组件时可以用@开头 @xxx=“” 给子组件传值:
自行增加了 @tag-click 和onTagClick 属性,确实有效
Vben项目中的父组件路径:src\layouts\default\header\components\notify\index.vue
// 父组件--
<Popover title="" trigger="click" :overlayClassName="`${prefixCls}__overlay`">
<Badge :count="count" dot :numberStyle="numberStyle">
<BellOutlined />
</Badge>
<template #content>
<Tabs>
<template v-for="item in listData" :key="item.key">
<Tabs.TabPane>
<template #tab>
{{ item.name }}
<span v-if="item.list.length !== 0">({{ item.list.length }})</span>
</template>
<!-- 绑定title-click事件的通知列表中标题是“可点击”的-->
<NoticeList
:list="item.list"
v-if="item.key === '1'"
@title-click="onNoticeClick"
@txt-click="consl"
/>
<NoticeList :list="item.list" v-else @txt-click="consl" @tag-click="onTagClick" />
</Tabs.TabPane>
</template>
</Tabs>
</template>
</Popover>
父组件–部分js
// 通过子组件的emit 触发txt-click 方法
function consl(e) {
console.log(e);
}
// 将该方法作为属性 传递给子组件(@title-click 相当于 :on-title-click) 在子组件中需要的时候调用
function onNoticeClick(record: ListItem) {
createMessage.success('你点击了通知,ID=' + record.id);
// 可以直接将其标记为已读(为标题添加删除线),此处演示的代码会切换删除线状态
record.titleDelete = !record.titleDelete;
}
// 将该方法作为属性 传递给子组件(@title-click 相当于 :on-tag-click) 在子组件中需要的时候调用
function onTagClick(record: ListItem) {
createMessage.success('你点击了通知,extra=' + record.extra);
}
Vben项目中的子组件:
<List :class="prefixCls" bordered :pagination="getPagination">
<template v-for="item in getData" :key="item.id">
<List.Item class="list-item">
<List.Item.Meta>
<template #title>
<div class="title">
<Typography.Paragraph
@click="handleTitleClick(item)"
:delete="!!item.titleDelete"
:ellipsis="
titleRows && titleRows > 0 ? { rows: titleRows, tooltip: !!item.title } : false
"
:content="item.title"
/>
<div class="extra" v-if="item.extra" @click="tagClick(item)">
<Tag class="tag" :color="item.color">
{{ item.extra }}
</Tag>
</div>
</div>
</template>
<template #avatar>
<Avatar v-if="item.avatar" class="avatar" :src="item.avatar" />
<span v-else> {{ item.avatar }}</span>
</template>
<template #description>
<div>
<div class="description" v-if="item.description">
<Typography.Paragraph
@click="txtClick(item.description)"
:ellipsis="
descRows && descRows > 0
? { rows: descRows, tooltip: !!item.description }
: false
"
:content="item.description"
/>
</div>
<div class="datetime">
{{ item.datetime }}
</div>
</div>
</template>
</List.Item.Meta>
</List.Item>
</template>
</List>
子组件—部分js
const props = defineProps({
list: {
type: Array as PropType<ListItem[]>,
default: () => [],
},
// ...
onTitleClick: {
type: Function as PropType<(Recordable) => void>,
},
onTagClick: {
type: Function as PropType<(Recordable) => void>,
},
});
console.log(props);
const emit = defineEmits(['update:currentPage', 'txt-click']);
function txtClick(txt: String) { // 通过常规emit 方式触发父组件的事件:@txt-click="consl"
emit('txt-click', txt);
}
// 通过父组件传递过来的属性函数来调用父组件的方法 子组件传值规则 onTitleClick
// 以on开头 在父组件调用时 直接用“@”代替 “:on-” 即::on-title-click 直接写成 @title-click
function handleTitleClick(item: ListItem) {
props.onTitleClick && props.onTitleClick(item);
}
// 本方法同理参考书写
function tagClick(item: ListItem) {
props.onTagClick && props.onTagClick(item);
}
查找官方文档也没找到相关的说明, 然后通过询问csdn的C一下,查询得到以下回复:
在Vue3中,props传值以on开头,在调用子组件时可以用@开头代表某个属性的原因是:这是Vue3中的一种新特性,叫做v-model指令的缩写语法。它使得我们在使用子组件时可以更加简便地传递数据和事件。
具体而言,如果你在子组件中定义了一个props属性名为"onXXX",那么在父组件中调用子组件时,可以用"@XXX"来代表这个属性。这样做的好处是,在父组件中使用子组件时,我们不需要再额外声明一个v-on指令来监听事件,而是可以直接用v-model指令来实现数据的双向绑定。
举个例子,假设我们在子组件中定义了一个props属性名为"onUpdateValue",那么在父组件中调用子组件时,可以这样写:
<template>
<child-component @update-value=“handleUpdateValue”></child-component>
</template>
<script>
import ChildComponent from “./ChildComponent.vue”;
export default {
components: { ChildComponent },
methods: {
handleUpdateValue(newValue) {
// 在这里处理数据更新的逻辑
},
},
};
</script>
在上面的代码中,我们使用了"@update-value"来代表子组件的"onUpdateValue"属性,同时给"@update-value"绑定了一个名为"handleUpdateValue"的方法来处理更新事件。这样,在子组件中更新数据时,就会自动触发父组件中的"handleUpdateValue"方法。