Skip to content
Have a clear structure

新的组件

Fragment

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

Teleport

  • 将包裹的 HTML 结构移动到指定元素的末尾
  • to 属性为 CSS 选择器 简易的模态框效果:
html
<teleport to="#root">
  <div v-if="isShow" class="mask">
    <div class="dialog">
      <h3>我是一个弹窗</h3>
      <button @click="isShow = false">关闭弹窗</button>
    </div>
  </div>
</teleport>
css
.mask {
  /* 遮罩层铺满窗口 */
  position: absolute;
  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%);
  text-align: center;
  width: 300px;
  height: 300px;
  background-color: green;
}

Suspense

  • 等待异步组件时渲染额外内容,让用户体验更好

异步引入组件:

js
import { defineAsyncComponent } from 'vue'
const Child = defineAsyncComponent(() => import('./components/Child.vue'))

使用 Suspense 包裹组件,实际上是往插槽填充内容,default 插槽填充组件内容,fallback 插槽填充组件加载时显示的内容:

html
<Suspense>
  <template v-slot:default>
    <Child />
  </template>
  <template v-slot:fallback>
    <h3>加载中,请稍等...</h3>
  </template>
</Suspense>

另外,若 Child 组件的 setup 函数返回一个 Promise 对象,也能渲染 fallback 里的内容:

js
async setup() {
  let sum = ref(0)
  return await new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve({sum})
    }, 3000)
  })
}