14、Vue 3 (2024 版)基础笔记 - 通过事件实现子组件传递数据给父组件

作者: 温新

图书: 【Vue 3 setup 使用实记】

阅读: 448

时间: 2024-11-20 01:27:16

通常,只能是父组件传递数据给子组件,若子组件想要传递数据给父组件,就需要通过 事件

这里我们使用上篇文章的组件进行演示。为了于便独立演示,这里还是把完整的代码写出来。

准备工作

1、创建父组件

src/components/comp/MainComp.vue

<template>
    <main>
        <h3>主体部分</h3>

        <!-- 传递对象给子组件 -->
        <ArticleComp
            v-for="article in articles" :key="article.id"
            :article="article"
        />
    </main>
</template>

<script setup lang="ts">
    import ArticleComp from "@/components/comp/article/ArticleComp.vue";

    // 从服务端请求的数据
    const articles = [
        {id:1, title:"坚持的意义是什么?"},
        {id:2, title:"什么是放下?"}
    ];
</script>

<style scoped>
    main {
        display: flex;
        justify-content: center;
        flex-direction: column;
        align-items: center;
        margin-top: 10px;
        background: lightblue;
        width: 100%;
        height: 100%;
        border-radius: 10px;
    }
</style>
2、创建子组件

src/components/comp/article/ArticleComp.vue

<template>
    <article>
        <h3>文章组件</h3>
        <div>
            <p>{{ article.id }}:{{ article.title }}</p>
        </div>
    </article>
</template>

<script setup lang="ts">
    const props = defineProps(['article', 'userinfo'])
</script>

<style scoped>
    article {
        margin-bottom: 5px;
        width: 100%;
        text-align: center;
        color: white;
        background: lightsteelblue;
    }
</style>
3、使用组件

src/App.vue

<template>
    <MainComp/>
</template>

<script setup lang="ts">
    import MainComp from "@/components/comp/MainComp.vue";
</script>

演示说明:MainComp 组件是 ArticleComp 的父组件,这里已经完成了父组件传递数据给子组件。

接下来,就演示子组件通过事件传递数据给父组件。

父组件监听子组件自定义事件

方式一:无参数传递

1、通过 $emit 发送自定义事件

src/components/comp/article/ArticleComp.vue

<template>
    <article>
        <h3>文章组件</h3>
        <div>
            <!-- 1、 子组件中,通过 $emit 自定义了一个 articleEvent 事件  -->
            <p @click="$emit('articleEvent')">{{ article.id }}:{{ article.title }}</p>
        </div>
    </article>
</template>

...
2、父组件监听子组件自定义事件

父组件中,可以通过 @ 或者 v-on 监听子组件的自定义事件名来监听事件。

src/components/comp/MainComp.vue

<template>
    <main>
        <h3>主体部分</h3>

        <!-- 父组件使用 @articleEvent 监听子组件的事件  -->
        <!-- articleEvent 必须是子组件发送的事件名 -->
        <!-- 父组件中定义一个方法来响应子组件 -->
        <ArticleComp
            v-for="article in articles" :key="article.id"
            :article="article"
            @article-event="getArticleInfo"
        />
    </main>
</template>

<script setup lang="ts">
    import ArticleComp from "@/components/comp/article/ArticleComp.vue";

    const articles = [
        {id:1, title:"坚持的意义是什么?"},
        {id:2, title:"什么是放下?"}
    ];

    const getArticleInfo = () => {
        alert(1)
    }
</script>

...

如此,就完成了子组件通过自定义事件向父组件传递数据。

方式二:无参数传递

src/components/comp/article/ArticleComp.vue

<template>
    <article>
        <h3>文章组件</h3>
        <div>
            <!-- 2、使用 emit 触发自定义事件 -->
            <p @click="emit('articleEvent')">{{ article.id }}:{{ article.title }}</p>
        </div>
    </article>
</template>

<script setup lang="ts">
    const props = defineProps(['article'])

    // 1、使用 defineEmits 函数进行自定义事件
    const emit = defineEmits(['articleEvent'])

    // 注意:当使用 emit 进行触发自定义事件时,
    // 此时,想在哪触发都可以
    setInterval(() => {
        emit('articleEvent')
    }, 3000)

</script>

...

子组件传递数据给父组件

方式一:使用 $emit

1、通过 $emit 发送自定义事件

src/components/comp/article/ArticleComp.vue

<template>
    <article>
        <h3>文章组件</h3>
        <div>
			<!-- 把 article 对象数据传递给父组件 -->
            <p @click="$emit('articleEvent', article)">{{ article.id }}:{{ article.title }}</p>
        </div>
    </article>
</template>

<script setup lang="ts">
    const props = defineProps(['article'])
</script>

...
2、父组件接收子组件数据

src/components/comp/MainComp.vue

<template>
    <main>
        <h3>主体部分</h3>
        <ArticleComp
            v-for="article in articles" :key="article.id"
            :article="article"
            @article-event="getArticleInfo(article)"
        />
        <p>来自子组件的文档:{{ art.title }}</p>
    </main>
</template>

<script setup lang="ts">
    import {ref} from 'vue'
    import ArticleComp from "@/components/comp/article/ArticleComp.vue";

    const articles = [
        {id:1, title:"坚持的意义是什么?"},
        {id:2, title:"什么是放下?"}
    ];

    interface Article {
        id: number;
        title: string;
    }
    
    const art = ref<Article>({});

    const getArticleInfo = (article:Article) => {
        art.value = article
        console.log(article)
    }
</script>

...

控制台输出

{id: 2, title: '什么是放下?'}
{id: 1, title: '坚持的意义是什么?'}

方式二:使用 emit 函数

src/components/comp/article/ArticleComp.vue

<template>
    <article>
        <h3>文章组件</h3>
        <div>

            <p @click="emit('articleEvent', article)">{{ article.id }}:{{ article.title }}</p>
        </div>
    </article>
</template>

<script setup lang="ts">
    const props = defineProps(['article'])
    const emit = defineEmits(['articleEvent'])
</script>

...

组件事件与数据绑定

子组件中,如何实时把数据传递给父组件?在子组件中可以通过 v-modelwatch 配合实现。

1、定义一个 search 子组件

src/components/comp/SearchComp.vue

<template></template>

<script setup lang="ts"></script>
2、引入组件

src/App.vue

<template>
    <SearchComp/>
</template>

<script setup lang="ts">
    import SearchComp from "./components/comp/SearchComp.vue";
</script>
3、子组件实时传递数据给父组件

src/components/comp/SearchComp.vue

<template>
    <p>子组件中的搜索内容:{{ content }}</p>
    <SearchComp @send-search="getSearch"/>
</template>

<script setup lang="ts">

    import SearchComp from "./components/comp/SearchComp.vue";
    import { ref } from "vue";

    const content = ref('')

    const getSearch = (data:string) => {
        content.value = data
    }
</script>
4、父组件实现输出

src/App.vue

<template>
    <p>子组件中的搜索内容:{{ content }}</p>
    <SearchComp @send-search="getSearch"/>
</template>

<script setup lang="ts">
    import SearchComp from "./components/comp/SearchComp.vue";
    import { ref } from "vue";

    const content = ref('')

    const getSearch = (data:string) => {
        content.value = data
    }
</script>
请登录后再评论