• 五、Vue3基础之五



    一、vue3 slot

    插槽是子组件中提供给父组件使用的一个占位符,父组件可以在这个占位符中填充任何模板代码,如html、组件等。
    子组件提供坑,坑里填什么由父组件决定。

    子组件挖坑:

    <template>
    
        <div>
            <div class="div1">
                
                <slot>slot>
            div>
            <div class="div2">
                
                <slot name="div2">slot>
            div>
            <div class="div3">
    
            div>
        div>
        
    template>
    
    <script setup lang='ts'>
    import { ref, reactive } from 'vue'
    
    script>
    
    <style lang='scss' scoped>
    .div1{
        width: 200px;
        height: 200px;
        background-color: yellow;
    }
    .div2{
        width: 200px;
        height: 200px;
        background-color: blueviolet;
    }
    .div3{
        width: 200px;
        height: 200px;
        background-color: pink
    }
    
    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

    父组件填坑

    <template>
        <div>
            右侧内容区域
            <A>
                
                <template v-slot>
                    <h2>匿名插槽h2>
                template>
                <template v-slot:div2>
                    <h2>具名插槽h2>
                template>
            A>
        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'
    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

    子组件通过插槽向父组件传数据
    子组件

    <template>
    
        <div>
            <div class="div1">
                
                <slot>slot>
            div>
            <div class="div2">
                <div v-for="(item, index) in data">
                    
                    <slot name="div2" :index="index" :data="item">slot>
                div>
                
            div>
            <div class="div3">
    
            div>
        div>
    
    template>
    
    <script setup lang='ts'>
    import { ref, reactive } from 'vue'
    type Person = {
        name: string, 
        age: number
    }
    const data = reactive<Person[]>([
        {
            name: '张三',
            age: 18
        },
        {
            name: '李',
            age: 19
        },
        {
            name: '王五',
            age: 20
        },
        {
            name: '赵六',
            age: 21
        },
    ])
    
    script>
    
    <style lang='scss' scoped>
    .div1{
        width: 200px;
        height: 200px;
        background-color: yellow;
    }
    .div2{
        width: 200px;
        height: 200px;
        background-color: blueviolet;
    }
    .div3{
        width: 200px;
        height: 200px;
        background-color: pink
    }
    
    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
    • 64
    • 65
    • 66

    父组件

    <template>
        <div>
            右侧内容区域
            <A>
                <template #default>
                    <h2>匿名插槽h2>
                template>
                <template v-slot:div2="{index, data}">
                    <h2>具名插槽--{{index}}--{{data.name}}--{{data.age}}h2>
                template>
            A>
        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'
    
    
    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

    动态插槽

    <template>
        <div>
            右侧内容区域
            <A>
                
                <template #[name]>
                    <h2>匿名插槽h2>
                template>
    
            A>
        div>
    template>
    
    <script setup lang='ts'>
    import { ref, reactive, markRaw } from 'vue'
    import A from './A.vue'
    
    let name = ref('div2')
    
    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

    二、异步组件

    我们打包发布的时候会打成一个js文件,如果定义成异步组件,就会单独打包成一个js文件,用到的时候再加载进来。
    在public文件下建一 个data.json文件,用来模拟数据

    [
        {
            "name": "张三"
        },
        {
            "name": "李四"
        },
        {
            "name": "王五"
        },
        {
            "name": "赵六"
        }
    ]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    在Content下建一个server.ts用来模拟axios,异步获取数据

    type NameList = {
        name: string
    }
    
    export const axios = (url:string):Promise<NameList[]> => {
        return new Promise((resolve) => {
            let xhr: XMLHttpRequest = new XMLHttpRequest()
            xhr.open('get', url)
            xhr.onreadystatechange = () => {
                if(xhr.readyState ===4 && xhr.status == 200){
                    setTimeout(()=>{
                        resolve(JSON.parse(xhr.responseText))
                    }, 2000)
                }
            }
        })
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    父组件

    <template>
        <div>
            右侧内容区域
            <Suspense>
                
                <template #default>
                    <C>C>
                template>
                
                <template #fallback>
                     loading......
                template>
            Suspense>
        div>
    template>
    
    <script setup lang='ts'>
    import { defineAsyncComponent } from 'vue'
    // 用defineAsyncComponent来加载异步组件
    const C = defineAsyncComponent(()=>import('./C.vue'))
    
    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

    子组件

    <template>
    
        <div>
            CCCCCCCCCCCCCCCCCCCC
            <ul v-for="item,index in list" :key="index">
                <li>{{item.name}}</li>
            </ul>
        </div>
    
    </template>
    
    <script setup lang='ts'>
    import { ref, reactive } from 'vue'
    import { axios } from './server'
    
    // 在public下的文件为什么这里请求是./data.json呢?
    // await自动获取到.then的数据
    const list = await axios('./data.json')
    console.log(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

    三、vue3 Teleport传送组件

    Vue3.0新特性之一,能够将我们的模板渲染到指定DOM节点,不受父组style,v-show等属性影响,但data,prop数据依旧能够共用的技术。
    Teleport节点搭载在其他指定的DOM节点下,完全不受父级style样式影响。

    <Teleport to="body">
         
        <A>A>
    Teleport>
    
    • 1
    • 2
    • 3
    • 4

    四、vue3 keep-alive缓存组件

    有时候我们希望组件被重新渲染影响使用体验,或者处于性能考虑,避免多次重复渲染降低性能,而是希望组件可以缓存下来维持当前的状态,这时候就要用到keep-alive组件。

    <keep-alive>
         
        <A v-if="flag"><A>
        <B v-else><B>
    keep-alive>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    使用了keep-alive包裹的组件新增了两个生命周期

    onActivated(()=>{
        console.log('keep-alive初始化')
    })
    onDeactivated(()=>{
        console.log('keep-alive卸载')
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    五、vue3 transition动画组件

    vue提供了transtion的封装组件,在下列情况中,可以给任何元素和组件添加进入、离开过渡

    • 条件渲染(使用v-if)
    • 条件展示(使用v-show)
    • 动态组件
    • 组件根节点

    案例:transition动画组件使用

    <template>
        <div>
            <button @click="flag=!flag">switchbutton>
            <transition name="fade">
                <div v-if="flag" class="box">div>
            transition>
        div>
    template>
    
    <script setup lang='ts'>
    import { ref } from 'vue'
    
    const flag = ref<boolean>(true)
    
    script>
    
    <style lang='scss' scoped>
    .box{
        width: 200px;
        height: 200px;
        background-color: palevioletred;
    }
    // 进入动画之前,具体的属性可翻看vue官方文档
    .fade-enter-from{
        width: 0;
        height: 0;
    }
    .fade-enter-active{
        transition: all 1.5s ease;
    }
    .fade-enter-to{
        width: 200px;
        height: 200px;
    }
    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

    vue3的动画组件有很多特征,可以自行看一下。

    六、Provide、Inject

    在这里插入图片描述
    在这里插入图片描述
    App.vue

    <template>
        <h1>App.vue根组件h1>
        <label>
            <input v-model="colorVal" value="red" name="color" type="radio">
            红色
        label>
        <label>
            <input v-model="colorVal" value="pink" name="color" type="radio">
            粉色
        label>
        <label>
            <input v-model="colorVal" value="yellow" name="color" type="radio">
            黄色
        label>
        
        <div class="box">div>
        <provideA>provideA>
    
    template>
    
    <script setup lang="ts">
    import {ref, provide} from 'vue'
    import provideA from './components/provideA.vue'
    const colorVal = ref<string>('red')
    // 将数据注入进去,子组件中就可以使用inject读取这个数据了
    provide('color', colorVal)
    script>
    
    <style lang="scss" scoped>
    .box{
        width: 50px;
        height: 50px;
        border: 1px solid red;
        background-color: v-bind(colorVal);
    }
    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

    provideA.vue

    <template>
    
        <h2>provideAh2>
        <div class="box">div>
        <provideB>provideB>
    template>
    
    <script setup lang='ts'>
    import { ref, reactive, inject } from 'vue'
    import { Ref } from 'vue'
    import provideB from './provideB.vue'
    const color = inject<Ref<string>>('color')
    
    
    script>
    
    <style lang='scss' scoped>
    .box{
        width: 50px;
        height: 50px;
        border: 1px solid red;
        // vue3中css可以使用v-bind绑定setup中的变量
        background-color: v-bind(color);
    }
    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

    provideB.vue

    <template>
    
        <h2>provideBh2>
        <div class="box">
    
        div>
    
    template>
    
    <script setup lang='ts'>
    import { ref, reactive, inject } from 'vue'
    import { Ref } from 'vue'
    const color = inject<Ref<string>>('color')
    
    script>
    
    <style lang='scss' scoped>
    .box{
        width: 50px;
        height: 50px;
        border: 1px solid red;
        background-color: v-bind(color);
    }
    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
  • 相关阅读:
    如何删除错误堆栈里的数据
    【驯服野生verilog-mode全记录】day1 —— 常用链接与基本命令模板
    联邦学习开源框架方案选型
    Linux下安装Mysql
    校招面试数据库原理知识复习总结三之SQL语句
    figma都有哪些小技巧,分享3个给你
    SpringMVC-----JSR303以及拦截器
    Linux操作系统之基础IO
    MySQL存储引擎介绍
    R语言隐马尔可夫模型HMM识别股市变化分析报告
  • 原文地址:https://blog.csdn.net/weixin_42710036/article/details/127614305