13、Vue 3 (2024 版)基础笔记 - 组件 & 组件间数据传递

作者: 温新

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

阅读: 81

时间: 2024-05-20 07:13:28

组件是对功能的拆分与复用。

关于组件,我们一直在使用,现在就来了解它吧。

1,组件的基础使用

1、创建组件

头部组件

src/components/comp/HeaderComp.vue

<template>
    <header>
        <h3>头部</h3>
    </header>
</template>

<script setup lang="ts">
</script>

<style scoped>
    * {
        margin: 0;
        padding: 0;
    }
    header {
        display: flex;
        justify-content: center;
        align-items: center;
        padding: 10px 0;
        background: black;
        color: white;
        border-radius: 10px;
        width: 100%;
        height: 32px;
    }
</style>

主体部分

src/components/comp/MainComp.vue

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

<script setup lang="ts">
</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/App.vue

<template>
	<!-- 2、使用组件 -->
    <HeaderComp/>
    <MainComp/>
</template>

<script setup lang="ts">
    // 1、引入组件
    import HeaderComp from "@/components/comp/HeaderComp.vue";
    import MainComp from "@/components/comp/MainComp.vue";
</script>
3、浏览查看效果

http://localhost:5173/ 打开你的地址就可以看到效果了。

这就是组件的基础使用。

2,嵌套组件

组件的基础使用 这个案例中,其实就已经在使用组件嵌套了。在 root 节点(也就是 App.vue) 中嵌套了 HeaderCompMainComp 这两个组件。

接下来就更深层次嵌套,在 MainComp 组件中嵌套组件。

1、创建组件

src/components/comp/article/ArticleComp.vue

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

<script setup lang="ts">

</script>

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

src/components/comp/MainComp.vue

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

        <ArticleComp/>
        <ArticleComp/>
        <ArticleComp/>
    </main>
</template>

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

<!-- ... 表示代码省略  -->
<style scoped>
    ...
</style>

3,全局组件

在上面的这些案例中,我们使用的都是局部组件。这里,我们学习一下全局组件的使用。

全局组件即一旦注册,在任何地方都可以直接调用。

1、创建组件

src/components/comp/FooterComp.vue

<template>
    <footer>
        <h3>底部区域</h3>
    </footer>
</template>

<script setup lang="ts">

</script>

<style scoped>
    footer {
        display: flex;
        justify-content: center;
        margin-top: 5px;
        background: black;
        color: white;
        border-radius: 10px;
    }
</style>
2、注册全局组件

src/main.ts

import { createApp } from 'vue'
import App from './App.vue'

// 1、引入全局组件
import FooterComp from "@/components/comp/FooterComp.vue";

const app = createApp(App)

// 2、注册全局组件
app.component('FooterComp', FooterComp)

app.mount('#app')
3、使用全局组件

src/App.vue

<template>
    <HeaderComp/>
    <MainComp/>
    <!-- 3、使用全局组件 -->
    <FooterComp/>
</template>

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

需要注意,我们没有在 App.vue 中引入 FooterComp 组件,而直接调用,因为它是全局组件了。

4,Props 组件间数据传递

在进行数据传递之前,我们先来梳理下目前文件之间的层级嵌套关系。

├── App.vue
├──── HeaderComp
├──── MainComp
│   	├── ArticleComp
├──── FooterComp

<script setup> 语法中,子组件接收父组件的数据使用 defineProps

4.1,传递静态数据

我们使用 AppFooterComp 进行静态数据传递的演示。App.vue 为父组件,FooterComp 为子组件,现在,演示 AppFooterComp 传递数据。

1、父组件向子组件传递数据

src/App.vue

<template>
    <HeaderComp/>
    <MainComp/>
    <!-- 使用自定义属性向子组件传递静态数据 -->
    <FooterComp title="Copyright © 2024 自如初" description="我的世界真奇妙"/>
</template>

<script setup lang="ts">
    import HeaderComp from "@/components/comp/HeaderComp.vue";
    import MainComp from "@/components/comp/MainComp.vue";
</script>
2、子组件使用 defineProps 接收数据

src/components/comp/FooterComp.vue

<template>
    <footer>
        <h3>底部区域</h3>
        <div>
            <!-- 使用数据 -->
            <p>{{ title }}</p>
            <p>{{ description }}</p>
        </div>
    </footer>
</template>

<script setup lang="ts">
    // 接收父组件传递的数据
    defineProps(['title', 'description'])
</script>

<style scoped>
    /* 注意:样式有变化 */
    footer {
        display: flex;
        flex-direction: column;
        align-items: center;
        margin-top: 5px;
        padding: 10px 0;
        background: black;
        color: white;
        border-radius: 10px;
    }
</style>

4.2,传递动态数据

会了静态传递数据,那么动态传递数据也就容易多了。我们基于静态传递数据的案例进行改造。

1、父组件传递动态数据给子组件

src/App.vue

<template>
    <HeaderComp/>
    <MainComp/>
    <FooterComp
        title="Copyright © 2024 自如初"
        description="我的世界真奇妙"

        :name="name"
        :age="age"
    />
</template>

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

    // 定义动态数据
    const name = "王美丽,"
    const age  = '19 岁啦'
</script>
2、子组件接收数据

src/components/comp/FooterComp.vue

<template>
    <footer>
        <h3>底部区域</h3>
        <div>
            <!-- 使用数据 -->
            <p>{{ title }}</p>
            <p>{{ description }}</p>
            <p>{{name}} {{ age}}</p>
        </div>
    </footer>
</template>

<script setup lang="ts">
    // 接收父组件传递的数据
    defineProps(['title', 'description', 'name', 'age'])
</script>

...

4.3,组件传递多种数据类型

对于基本数据类型,我们新建一个组件来演示。对于数组和对象,我们还是回归到 MainComp 组件中。

准备工作

1、创建组件

src/components/PropComp.vue

<template></template>

<script setup lang="ts"></script>
2、使用组件

src/App.vue

<template>
	...

    <PropComp/>
</template>

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

	...
</script>

传递基本数据类型:Number,Boolean

1、父组件传递基础类型数据给子组件

src/App.vue

<template>
	...

    <PropComp :number="number" :bool="bool"/>
</template>

<script setup lang="ts">
	...
    
    // 传递 Number、Boolean
    const number = 10
    const bool = true
</script>
2、子组件接收数据

src/components/PropComp.vue

<template>
    <div>
        <h4>演示传递 Number & Boolean</h4>
        <p>{{ number }}</p>
        <p>{{ bool }}</p>
    </div>
</template>

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

传递数组给子组件

注意:文件发生了变化。

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>

...
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'])
</script>

...

传递对象给子组件

1、父组件传递对象数据

src/components/comp/MainComp.vue

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

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

<script setup lang="ts">
	...

    const userinfo = {
        name:"王丽丽",
        age:19
    }
</script>

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

src/components/comp/article/ArticleComp.vue

<template>
    <article>
        <h3>文章组件</h3>
        <div>
            <!-- 数组数据 -->
            <p>{{ article.id }}:{{ article.title }}</p>
            <!-- 对象数据 -->
            <p>{{ userinfo.name }} {{ userinfo.age }}</p>
        </div>
    </article>
</template>

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

...

4.4,Props 数据校验

1、修改组件

src/App.vue

<template>
    <PropComp :number="number" :bool="bool" :username="username" :users="users"/>
</template>

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

    // 传递 Number、Boolean
    const number = 10
    const bool = true
    const username = "王丽丽"
    const users = ["小丽", "小美"]
</script>
2、接收数据

src/components/PropComp.vue

<template>
    <div>
        <h4>演示传递 Number & Boolean</h4>
        <p>{{ number }}</p>
        <p>{{ bool }}</p>
        <p>{{ username }}</p>
        <ul>
            <li v-for="(user, index) in users" :key="index">{{ user }}</li>
        </ul>
    </div>
</template>

<script setup lang="ts">
    const props = defineProps({
        // number 必须是数字类型且为必填
        number:{
            type:Number,
            required:true
        },
        // bool 必须是 boolean 类型
        bool:{
            type:Boolean
        },
        // 既可以是 string 也可以是 number,且有默认值
        username:{
            type:[String, Number],
            default:"王美美"
        },
        users: {
            type:Array,
            default() {
                return ["小新"]
            }
        }
    })
</script>
请登录后再评论