1、异步请求组件 Suspense
Suspense是Vue3推出的一个内置的特殊组件,有两个template slot,刚开始会渲染一个fallback内容,直到达到某个条件以后才会渲染正式的内容。
如果使用Suspense,在setup( )中需要返回一个promise,而不是直接返回一个对象。
Async1.vue

<template>
  <h1>{{result}}</h1>
</template>

<script>
import { defineComponent }  from "vue";
export default defineComponent({
  setup() {
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve({
          result: "异步组件"
        });
      }, 2000)
    })
  }
})
</script>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

使用时

<template>
  <div>
    <Suspense>
      <template #default>
        <async-one />
      </template>
      <template #fallback>
        <h1>Loading...</h1>
      </template>
    </Suspense>
  </div>
</template>

<script>
import AsyncOne from '../../components/Async1.vue'

export default {
  name: "suspense",
  components:{
    AsyncOne
  }
}
</script>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

Suspense 中可以添加多个异步组件,template default包裹多个组件,等这些个result都加载好了一起进行展示。

<template>
  <div>
    <Suspense>
      <template #default>
        <div>
          <async-one />
          <async-two />
        </div>
      </template>
      <template #fallback>
        <h1>Loading...</h1>
      </template>
    </Suspense>
  </div>
</template>

<script>
import AsyncOne from '../../components/Async1.vue'
import AsyncTwo from '../../components/Async2.vue'

export default {
  name: "suspense",
  components:{
    AsyncOne,
    AsyncTwo
  }
}
</script>
  • 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

异步请求错误处理onErrorCaptured
在异步请求中必须要作的一件事情,就是要捕获错误,因为我们没办法后端给我们返回的结果,也有可能服务不通,所以一定要进行捕获异常和进行处理。
在vue3.x的版本中,可以使用onErrorCaptured这个钩子函数来捕获异常,钩子函数要求我们返回一个布尔值,代表错误是否向上传递
Async.vue

<template>
  <h1>{{result}}</h1>
</template>

<script>
import { defineComponent }  from "vue";
export default defineComponent({
  setup() {
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        reject({
          result: "异步组件"
        });
      }, 2000)
    })
  }
})
</script>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
<template>
  <div>
    <Suspense>
      <template #default>
        <async-one />
      </template>
      <template #fallback>
        <h1>Loading...</h1>
      </template>
    </Suspense>
  </div>
</template>

<script>
import { onErrorCaptured } from "vue";
import AsyncOne from '../../components/Async1.vue'

export default {
  name: "suspense",
  components:{
    AsyncOne
  },
  setup() {
    onErrorCaptured((error) => {
      console.log(error);
      return true;
    })

    return {};
  }
}
</script>
  • 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

在这里插入图片描述

2、Teleport
Teleport 是一种能够将我们的模板移动到 DOM 中 Vue app 之外的其他位置的技术
如果我们嵌套在 Vue 的某个组件内部,那么处理嵌套组件的定位、z-index 和样式就会变得很困难。
使用Teleport 就可以方便的解决组件间 css 层级问题
要使用teleport,首先要在页面上添加一个元素,我们要将模态内容移动到该页面

<!-- index.html -->
<body>
  <div id="app"></div>
  <div id="modal-container"></div>
</body>
  • 1
  • 2
  • 3
  • 4
  • 5

我们将模态内容包装在 teleport 组件中,还需要指定一个 to 属性,以标识目标元素,此处为#modal-container

<template>
  <div>
    <teleport to="#modal-container" v-if="show">
      <div class="modal-container">
         弹窗内容
      </div>
    </teleport>
    <van-button type="primary" @click="openDialog">弹窗</van-button>
  </div>
</template>

<script>
import {
  ref
} from "vue"
export default {
  name: 'teleport',
  setup() {
    const show = ref(false);

    const openDialog = () => {
      show.value = true;

      setTimeout(() => { // 弹窗的显示时常
        show.value = false;
      }, 1500)
    }

    return {
      show,
      openDialog
    }
  }
}
</script>

<style scoped>
.modal-container {
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  padding: 10px 20px;
  background: black;
  border-radius: 40px;
  opacity: 0.7;
  color: white;
  font: normal 16px/20px arial;
}
</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

在同一目标上使用多个teleport

<template>
  <div>
    <teleport to="#modal-container" v-if="show">
      <div class="modal-container">
         弹窗内容
      </div>
    </teleport>
    <teleport to="#modal-container" v-if="show">
      <div class="modal-container">
         弹窗内容2
      </div>
    </teleport>
    <van-button type="primary" @click="openDialog">弹窗</van-button>
  </div>
</template>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

对于这种情况,多个teleport组件可以将其内容挂载到同一个目标元素。顺序将是一个简单的追加——稍后挂载将位于目标元素中较早的挂载之后

源码:https://gitee.com/smallgrey/new-features-of-vue3
微信公众号:趣享编程