Fragment虚拟元素
中,该元素不会解析到页面上。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>
我们之前都是使用 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>
<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>
如果使用了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>