Vue3的新组件Fragment、Fragment、Suspense

Fragment

  • 在Vue2中:组件必须有一个根标签
  • 在Vue3中:组件可以没有根标签,但内部会将多个标签包含在一个Fragment虚拟元素中,该元素不会解析到页面上。
    好处:减少标签层级,减小内存占用

Teleport

Teleport是一种能够将我们的组件html结构移动到指定位置的技术。
eg:将弹窗移动到body中。
弹窗原本是嵌套在多级子组件中:
在这里插入图片描述
如果使用Teleport标签包裹,利用to属性可以跳转到任意位置
eg:跳转到body中:

<template>
    <div>
        <button @click="isShow=true">点我弹个窗</button>
        <teleport to="body">
        <div v-if="isShow" class="mask">
        <div v-if="isShow" class="dialog">
            <h3>我是一个弹窗</h3>
            <button @click="isShow=false">关闭弹窗</button>
        </div>
        </div>
        </teleport>
    </div>
</template>

<script>
import {
      
      ref} from "vue"
export default {
      
      
    name: 'DialogVue',
    setup() {
      
      
        let isShow = ref(false)
        return{
      
      isShow}
    }
}
</script>

<style>

.dialog{
      
      
    text-align: center;
    width: 300px;
    height: 150px;
    background-color:rgb(11, 59, 11);

    position:absolute;
    top:50%;
    left:50%;
    transform: translate(-50%,-50%);
}
.mask{
      
      
    position: absolute;
    top:0;
    bottom:0;
    left:0;
    right:0;
    background-color:rgba(0,0,0,0.5) ;
}

</style>

效果:
在这里插入图片描述
在这里插入图片描述

Suspense

异步组件引入

静态引入

我们之前都是使用 import Child from './components/Child'这种方式引入组件的,这种方式叫做静态引入
静态引入的特点是只要引入的组件没出来页面就不进行显示。
eg:App组件中嵌套着Child子组件,使用静态引入的方式的话,如果child组件没有加载进来,app组件是不会显示在页面上的,所以App组件最终会和Child组件一同渲染到页面上

动态引入(异步引入)

// defineAsyncComponent定义一个异步组件
import {
    
     defineAsyncComponent } from 'vue'
const Child = defineAsyncComponent(()=>import('./components/Child'))//动态引入(异步引入)

上述引入方法就是异步引入。
特点是哪个组件先加载好就先显示哪个组件。
eg:App组件中嵌套着Child子组件,使用异步引入的方式的话,如果child组件没有加载进来,app组件已经加载好了,那app组件就会先显示在页面上,Child组件什么时候加载完什么时候在进行显示。

所以异步引入组件可能会出现页面抖动的现象,为了解决这个现象引入Suspense

Suspense

Suspense是一个标签,他底部的实现原理是使用插槽实现的。
使用格式:

    <Suspense>
      <template v-slot:default>
        <组件名 />
      </template>
      <template v-slot:fallback>
        <h3>如果组件加载不出来显示的内容</h3>
      </template>
    </Suspense>

使用:
eg:
App.vue:

<template>
  <div class="app">
    <h2>我是app组件</h2>
    <Suspense>
      <template v-slot:default>
        <Child />
      </template>
      <template v-slot:fallback>
        <h3>加载中...</h3>
      </template>
    </Suspense>
  </div>
</template>

<script>
// import Child from './components/Child'//静态引入
// defineAsyncComponent定义一个异步组件
import {
      
       defineAsyncComponent } from 'vue'
const Child = defineAsyncComponent(()=>import('./components/Child'))//动态引入(异步引入)
export default {
      
       
  name: 'AppVue',
  components: {
      
       Child },
}
</script>

<style>
.app {
      
      
  background: #333;
  padding: 10px;
}
</style>

在这里插入图片描述

setup返回Promise对象

如果使用了Suspense和异步组件,那么setup也可以返回Promise对象了。
Child.vue:

<template>
    <div class="child">
        <h2>我是child组件</h2>
        {
   
   {sum}}
    </div>
</template>

<script>
import {
      
       ref } from '@vue/reactivity'
export default {
      
      
    name: 'ChildVue',
    setup() {
      
      
        let sum = ref(0)
        return new Promise((resolve, reject) => {
      
      
            setTimeout(() => {
      
      
                resolve({
      
      sum})
            },1000)
        })
    }
}
</script>
<style>

.child {
      
      
    background: rgb(225, 205, 148);
    padding: 10px;
}
</style>

App.vue:

<template>
  <div class="app">
    <h2>我是app组件</h2>
    <Suspense>
      <template v-slot:default>
        <Child />
      </template>
      <template v-slot:fallback>
        <h3>加载中...</h3>
      </template>
    </Suspense>
  </div>
</template>

<script>
// import Child from './components/Child'//静态引入
// defineAsyncComponent定义一个异步组件
import {
      
       defineAsyncComponent } from 'vue'
const Child = defineAsyncComponent(()=>import('./components/Child'))//动态引入(异步引入)
export default {
      
       
  name: 'AppVue',
  components: {
      
       Child },
}
</script>

<style>
.app {
      
      
  background: #333;
  padding: 10px;
}
</style>

在这里插入图片描述
那么setup也可以使用async修饰了,因为await的返回值就是Promise
child.vue

<template>
    <div class="child">
        <h2>我是child组件</h2>
        {
   
   {sum}}
    </div>
</template>

<script>
import {
      
       ref } from '@vue/reactivity'
export default {
      
      
    name: 'ChildVue',
    async setup() {
      
      
        let sum = ref(0)
       const p = new Promise((resolve, reject) => {
      
      
            setTimeout(() => {
      
      
                resolve({
      
      sum})
            },1000)
       })
        return await p;
    }
}
</script>
<style>

.child {
      
      
    background: rgb(225, 205, 148);
    padding: 10px;
}
</style>

猜你喜欢

转载自blog.csdn.net/mantou_riji/article/details/125980334