• 四、Vue3基础四



    一、vue3 父子组件传参

    **

    父组件向子组件传递参数

    **
    父组件通过v-bind绑定一个数据,然后子组件通过defineProps接受传过来的值。
    字符串类型不需要v-bind

    父组件中向子组件传递数据(字符串)的方法

    <template>
        <div class="container">
            <div class="left-menu">
                
                <Menu title="这个字符串可以传到Menu这个组件中">Menu>
            div>
            <div class="right">
                <Header class="header">Header>
                <Content class="content">Content>
            div>
        div>
        
    
    template>
    
    <script setup lang='ts'>
    import Menu from './Menu/index.vue'
    import Header from './Header/index.vue'
    import Content from './Content/index.vue'
    
    script>
    
    <style lang='scss' scoped>
    .container{
        display: flex;
        .left-menu{
            width: 20%;
            background-color: yellowgreen;
        }
        .right{
            width: 80%;
            border:1px solid pink;
            flex-flow: column wrap;
            .header{
                width:100%;
                height: 200px;
                border: 1px solid yellowgreen;
            }
            .content{
                width: 100%;
                height: 200px;
                border: 1px solid burlywood;
            }
        }
    }
    style>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46

    子组件Menu.vue中接收父组件传递过来的字符串

    <template>
        <div class="menu">
            左边菜单区域 <br>
            {{title}}
        div>
    template>
    
    <script setup lang='ts'>
    // 接收来自父组件传递来的数据
    // 传递过来的数据用一个类型约束一下
    type Props = {
        title:string
    }
    defineProps<Props>()
    script>
    
    <style lang='scss' scoped>
    style>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    从父组件传递复杂数据类型到子组件中

    父组件代码

    <template>
    
        <div class="container">
            <div class="left">
                
                <Menu class="menu" title="将这个title传到Menu子组件中" :data="list">Menu>
            div>
            <div class="right">
                <Header class="header">Header>
                <Content class="content">Content>
            div>
        div>
    
    template>
    
    <script setup lang='ts'>
    import Menu from './Menu/index.vue'
    import Header from './Header/index.vue'
    import Content from './Content/index.vue'
    import { ref, reactive } from 'vue'
    
    const list = ref<number[]>([1, 2, 3])
    
    script>
    
    <style lang='scss' scoped>
    .container{
        display: flex;
        flex-flow: row wrap;
        .left{
            width: 20%;
            .menu{
                background-color: rebeccapurple;
            }
        }
        .right{
            width: 80%;
            .header{
                width: 100%;
                height: 300px;
                background-color: palevioletred;
            }
            .content{
                width: 100%;
                height: 300px;
                background-color: yellowgreen;
            }
        }
    }
    style>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50

    子组件代码

    <template>
    
        <div>
            左侧菜单区域 <br>
            {{title}} <br>
            {{data}}
        div>
    
    template>
    
    <script setup lang='ts'>
    import { ref, reactive } from 'vue'
    
    type Props = {
        title: string,
        // 接收父组传递过来数组数据,key要和v-bind:data一致
        data: number[]
    }
    defineProps<Props>()
    
    script>
    
    <style lang='scss' scoped>
    
    style>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    子组件向父组件传递参数

    子组件通过事件向父组件传递参数
    子组件

    <template>
    
        <div>
            左侧菜单区域 <br>
            <button @click="clickTap">派发事件button>
        div>
    
    template>
    
    <script setup lang='ts'>
    import { ref, reactive } from 'vue'
    const list = reactive<number[]>([8, 8, 8])
    
    // defineEmits() 自定义一个事件,这个事件在父组件中可以拿到,返回一个函数
    const emit = defineEmits(['on-click'])
    const clickTap = ()=>{
        // 通过这个函数参数将数据传到父组件中
        emit('on-click', list)
    }
    
    script>
    
    <style lang='scss' scoped>
    
    style>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    父组件

    <template>
    
        <div class="container">
            <div class="left">
                
                
                <Menu class="menu" title="将这个title传到Menu子组件中" :data="list" @on-click="getList">Menu>
            div>
            <div class="right">
                <Header class="header">Header>
                <Content class="content">Content>
            div>
        div>
    
    template>
    
    <script setup lang='ts'>
    import Menu from './Menu/index.vue'
    import Header from './Header/index.vue'
    import Content from './Content/index.vue'
    import { ref, reactive } from 'vue'
    
    const list = ref<number[]>([1, 2, 3])
    
    // 接收子组件传递过来的数据
    const getList = (list:number[])=>{
        console.log(list, '子组件传递过来的list')
    }
    
    script>
    
    <style lang='scss' scoped>
    .container{
        display: flex;
        flex-flow: row wrap;
        .left{
            width: 20%;
            .menu{
                background-color: rebeccapurple;
            }
        }
        .right{
            width: 80%;
            .header{
                width: 100%;
                height: 300px;
                background-color: palevioletred;
            }
            .content{
                width: 100%;
                height: 300px;
                background-color: yellowgreen;
            }
        }
    }
    style>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56

    父组件中拿子组件实例

    父组件

    <template>
    
        <div class="container">
            <div class="left">
                
                <Menu class="menu" ref="menu" >Menu>
            div>
            <div class="right">
                <Header class="header">Header>
                <Content class="content">Content>
            div>
        div>
    
    template>
    
    <script setup lang='ts'>
    import Menu from './Menu/index.vue'
    import Header from './Header/index.vue'
    import Content from './Content/index.vue'
    import { ref, onMounted } from 'vue'
    
    const menu = ref(null)
    
    onMounted(()=>{
        // 如果子组件不暴躁数据出来,你什么都拿不到
        console.log(menu.value)
    })
    
    script>
    
    <style lang='scss' scoped>
    .container{
        display: flex;
        flex-flow: row wrap;
        .left{
            width: 20%;
            .menu{
                background-color: rebeccapurple;
            }
        }
        .right{
            width: 80%;
            .header{
                width: 100%;
                height: 300px;
                background-color: palevioletred;
            }
            .content{
                width: 100%;
                height: 300px;
                background-color: yellowgreen;
            }
        }
    }
    style>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55

    子组件

    <template>
    
        <div>
            左侧菜单区域 <br>
        div>
    
    template>
    
    <script setup lang='ts'>
    import { ref, reactive } from 'vue'
    const list = reactive<number[]>([8, 8, 8])
    const person = {
        name: '张三',
        age: 30
    }
    
    //将子组件的数据暴露出去,父组件才能拿到这些数据
    defineExpose({
        list,
        person,
    })
    
    script>
    
    <style lang='scss' scoped>
    
    style>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    父组件如果没传值给子组件,子组件设置默认值

    子组件

    <template>
    
        <div>
            左侧菜单区域 <br>
            {{title}} <br>
            {{data}}
        div>
    
    template>
    
    <script setup lang='ts'>
    import { ref, reactive } from 'vue'
    
    type Props = {
        title?: string,
        data?: number[]
    }
    withDefaults(defineProps<Props>(), {
        title: '父组件没传值给我',
        // 复杂数据需要一个函数返回值
        data: () => [0, 0, 0]
    })
    
    script>
    
    <style lang='scss' scoped>
    
    style>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    二、全局组件、局部组件、递归组件

    组件使用频率非常高(table, input)等,这些组件几乎每个页面都在使用便可以封装成全局组件
    在一个组件A通过import去引入别的组件B称之为局部组件
    递归组件和我们写程序的递归一个道理,自己调用自己,通过一个条件来结束递归,不然会导致内存泄漏

    全局组件

    定义一个全局组件

    <template>
    
        <div>
            <h2>我是全局组件card</h2>
        </div>
    
    </template>
    
    <script setup lang='ts'>
    import { ref, reactive } from 'vue'
    
    </script>
    
    <style lang='scss' scoped>
    
    </style>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    将全局组件注册到vue实例上:main.ts

    import { createApp } from 'vue'
    import App from './App.vue'
    // 引入一下全局组件
    import Card from './components/card/index.vue'
    
    // 在vue实例上挂载全局组件
    createApp(App).component('Card', Card).mount('#app')
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    递归组件

    src\components\Tree\index.vue
    应用场景,分组菜单
    Menu.vue

    <template>
    
        <div>
            左侧菜单区域 <br>
            <Tree :data="data">Tree>
        div>
    
    template>
    
    <script setup lang='ts'>
    import Tree from '../../components/Tree/index.vue'
    import { ref, reactive } from 'vue'
    import { title } from 'process';
    
    type TreeList = {
        title: string, 
        icon?: string,
        children?:TreeList[]
    }
    
    const data = reactive<TreeList[]>([
        {
            title: 'm-1',
            children:[
                {
                    title: 'm-1-1',
                    children:[
                        {
                            title: 'm-1-1-1'
                        }
                    ]
                }
            ]
        },
        {
            title: 'm-2',
            children:[
                {
                    title: 'm-2-1',
                    children:[
                        {
                            title: 'm-2-1-1',
                            children: [
                                {
                                    title: 'm-2-1-1-1'
                                }
                            ]
                        }
                    ]
                }
            ]
        },
        {
            title: 'm-3'
        }
    ])
    
    
    script>
    
    <style lang='scss' scoped>
    
    style>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63

    Tree.vue

    <template>
    
        <div>
            <ul v-for="(item,index) in data" :key="index">
                <li>{{item.title}}li>
                
                <Tree v-if="item?.children?.length" :data="item.children">Tree>
            ul>
        div>
    
    template>
    
    <script setup lang='ts'>
    import { ref, reactive } from 'vue'
    // 引入它自身
    import Tree from './index.vue'
    
    type TreeList = {
        title: string, 
        icon?: string,
        children?:TreeList[]
    }
    
    type Props = {
        data?: TreeList[]
    }
    defineProps<Props>()
    
    script>
    
    <style lang='scss' scoped>
    
    style>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    三、动态组件

    多个组件使用同一个挂载点,并动态切换,这就是动态组件

    
    <component :is="A">component>
    
    • 1
    • 2

    在Content下建A.vue B.vue C.vue
    index.vue

    <template>
        <div>
            右侧内容区域
            <div class="tab">
                
                <div @click="switchCom(item)" :key="item.name" v-for="item in data">{{item.name}}div>
            div>
            <component :is="current.comName">component>
        div>
    
    template>
    
    <script setup lang='ts'>
    import { ref, reactive, markRaw } from 'vue'
    import A from './A.vue'
    import B from './B.vue'
    import C from './C.vue'
    
    type Tabs = {
        name: string, 
        comName: any
    }
    
    // Pick 从Tabs中将'comName'抽取出来组成一个新类型如下:
    // type Com = { comName:any }
    type Com = Pick<Tabs, 'comName'>
    
    const data = reactive<Tabs[]>([
        {
            name: '我是A组件',
            // 使用markRaw表示组件A不需要响应式
            comName: markRaw(A)
        },
        {
            name: '我是B组件',
            comName: markRaw(B)
        },
        {
            name: '我是C组件',
            comName: markRaw(C)
        },
    ])
    
    let current = reactive<Com>({
        // 默认显示的A组件
        comName:data[0].comName
    })
    
    const switchCom = (item:Tabs) =>{
        current.comName = item.comName
    }
    
    script>
    
    <style lang='scss' scoped>
    
    style>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
  • 相关阅读:
    qml保姆级教程二:qml基本数据类型
    HTML5 和 CSS3 的新特性--品优购main主体模块制作
    树莓派之树莓派系统安装
    微服务--数据同步
    android 12.0app应用卸载黑名单
    Ruby on Rails已死?GitLab:我还在用呢!
    notejs+nvm+angular+typescript.js环境 Hertzbeat 配置
    Go 项目代码布局
    idea如何配置或者创建mybatis的xml文件 idea如何配置或者创建mybatis的配置文件
    自动打包压缩备份下载及删除 bat脚本命令
  • 原文地址:https://blog.csdn.net/weixin_42710036/article/details/127603669