1.Fragment —— 片段组件
-  
在Vue2中: 组件必须有一个根标签。
 -  
在Vue3中: 组件可以没有根标签, 内部会将多个标签包含在一个内置Fragment虚拟元素中, 最后是不参与页面渲染的!
 -  
好处: 减少标签层级, 减小内存占用。
 
<template>
    <fragment>
      .....
    </fragment>
</template>
 

2.Teleport——瞬间移动组件
什么是Teleport?—— Teleport 是一种能够将我们的组件html结构移动到指定位置的技术。
基础语法
<!--to属性的属性值: 是css的选择器 -->
<teleport to="移动位置">
	<div v-if="isShow" class="mask">
		<div class="dialog">
			<h3>我是一个弹窗</h3>
			<button @click="isShow = false">关闭弹窗</button>
		</div>
	</div>
</teleport> 
 
使用场景 ?
复用 Dialog 组件时 ,html结构会很深层次! 编写Dialog 组件样式、定位等css属性就不容易控制!Teleport 瞬移组件可以把藏的深层次的组件的html结构,给它拎出来,放置到指定节点位置元素下,方便css样式的可控性!
src/components/Dialog.vue
<template>
  <div>
    <button @click="isShow = !isShow">点我谈个窗</button>
   
    <!-- 使用瞬移组件: 将telepor 组件包裹的html结构,瞬移到body节点下  -->
    <teleport to="body">
      <!-- 遮罩层弹窗是一体的给遮罩层上控制、遮罩层显示顺带着弹窗就出来了; 很多ui组件也是这样控制的 -->
      <!-- v-if= false: 代表直接将dom元素节点直接移除 -->
      <div v-if="isShow" class="mask">
        <div class="dialog">
          <h3>我是一个弹窗</h3>
          <h4>我是一下内容</h4>
          <button @click="isShow = !isShow">关闭弹窗</button>
        </div>
      </div>
    </teleport>
  </div>
</template>
<script>
import { ref } from "vue";
export default {
  name: "Dialog",
  // 数据驱动着页面的显示
  setup() {
    let isShow = ref(false);
    return { isShow };
  },
};
</script>
<style scoped>
.mask {
  position: relative;
  /* 将元素撑开 */
  top: 0; bottom: 0; left: 0;right: 0;
  background-color: rgba(0, 0, 0, 0.5);
}
.dialog {
  position: absolute;
  top: 50%;left: 50%;
  transform: translate(-50%, -50%);
  width: 300px;
  height: 300px;
  background-color: pink;
  opacity: 0.7;
  text-align: center;
  border-radius: 10%;
}
</style> 
src/components/Son.vue
<template>
  <div class="son">
    <h3>我是Son组件!</h3>
    <!-- 使用Dialog组件, 但是Dialog组件的html 不在.son div的结构下,而是瞬移到了body节点下-->
    <Dialog/>
  </div>
</template>
<script>
import Dialog from './Dialog.vue'
export default {
  name: "Son",
  components: {Dialog}
};
</script>
<style>
.son {
  background-color: orange;
  padding: 10px;
}
</style> 
 

3.Suspense——异步组件
Suspense——Vue3中的新组件,并且官方说这个组件目前属于实验阶段! 以后与这个组件相关的API,或者说一些写法还有可能改!
Suspense 等待异步组件时渲染一些额外内容,让应用有更好的用户体验。
使用步骤:
1.异步引入组件
import {defineAsyncComponent} from 'vue'
const Child = defineAsyncComponent(()=>import('./components/Child.vue')) 
2.使用Suspense包裹组件,并配置好default 与 fallback
<template>
	<div class="app">
		<h3>我是App组件</h3>
		<Suspense>
			<template v-slot:default>
				<Child/>
			</template>
			<template v-slot:fallback>
				<h3>加载中.....</h3>
			</template>
		</Suspense>
	</div>
</template> 
eg:演示案例, 异步加载组件
src/App.vue
<template>
  <div class="app">
    <h1>我是App组件</h1>
    <!-- 
      Suspense: 异步组件
       1.底层也是用插槽实现的; 
       2.内部准备好了两个插槽, default展示真实放置的内容、
    -->
    <Suspense>
      <!-- 放置真正所展示的组件、注意: 指明插槽名是 default, 因为内部是写了两个插槽  -->
      <template v-slot: default>
        <Child></Child>
      </template>
      <!-- 由于某种原因 Child 组件加载慢了! 就会展示插槽名为 fallback 中的内容信息  -->
      <template v-slot:fallback>
        <h3>加载中,稍等...</h3>
      </template>
    </Suspense>
  </div>
</template>
<script>
// app、child 组件都属于静态组件
import { defineAsyncComponent } from "vue";
/* 
  静态引用 
    解析过程: 只要没有引入 Child 组件成功, 整个App 组件都不进行渲染! 
    缺点: 同步执行代码,会造成阻塞渲染页面白屏!  
*/
// import Child from "./components/Child";
/*
  动态、异步引入
    解析过程: 组件异步加载, 不会阻塞进程!
    缺点: 异步加载成功代码,间接的渲染到页面, 会造成页面的抖动、用户体验效果不好! 
*/
const Child = defineAsyncComponent(() => import("./components/Child"));
export default {
  name: "App",
  components: { Child },
  setup() {},
};
</script>
<style>
.app {
  background-color: gray;
  padding: 10px;
}
</style>
 
src/components/Child.vue
<template>
  <div class="child">
    <h1>我是Child组件!</h1>
    {{ sum }}
  </div>
</template>
<script>
import {ref} from 'vue'
export default {
  name: "Child",
  setup() {
    let sum = ref(0)
    // 让组件等一等 
    return new Promise((resolve, reject) =>{
      setTimeout(()=>{
        resolve({sum})
      }, 1000)
    })
  }
};
</script>
<style>
.child {
  background-color: skyblue;
  padding: 10px;
}
</style> 
 
 
                


















