当前位置:   article > 正文

vue3新特性-Suspense和Teleport_vue3 teleport、suspense等新特性

vue3 teleport、suspense等新特性

目录

前言

Suspense【试验性,可能变动,生产环境请勿使用】

实例:有一个组件的一些数据需要异步请求,请求完成后再渲染。

vue2实现

vue3-suspense 实现

注意事项

Teleport【传送】

实例: 实现一个点击按钮做 inx++,并展示出inx的功能。

vue2实现

vue3-teleport 实现

注意事项

总结


前言

阅读vue3源码的时候,发现会根据不同shapeFlag来做不一样的渲染,进而发现了vue3的一些新特性。好吧,我承认这个先后顺序可能有点点反。好了,让我们进入正题吧。

Suspense【试验性,可能变动,生产环境请勿使用】

官方说明:在正确渲染组件之前进行一些异步请求是很常见的事。suspense允许将等待过程提升到组件树中处理,而不是在单个组件中。

实例:有一个组件的一些数据需要异步请求,请求完成后再渲染。

为了显示友好,我们会在请求返回前显示一个Loading。

进入页面,显示 Loading,3秒后,显示为 Hello 

vue2实现

在vue2中,通常我们是定义一个变量来操作这个loading的显示与否

  1. <template>
  2. <div class="pager">
  3. <div v-if="loading">Loading</div>
  4. <div v-else>{{data}}</div>
  5. </div>
  6. </template>
  7. <script>
  8. export default {
  9. data() {
  10. return {
  11. loading: true,
  12. data: ''
  13. }
  14. },
  15. created() {
  16. this.load();
  17. },
  18. methods: {
  19. load() {
  20. this.loading = true;
  21. return new Promise((resolve) => {
  22. setTimeout(()=>{
  23. this.data= 'hello'
  24. this.loading = false;
  25. resolve('hello')
  26. }, 3000)
  27. })
  28. }
  29. }
  30. }
  31. </script>

vue3-suspense 实现

  • 父组件
  1. //父组件
  2. <script setup>
  3. import HelloWorld from './components/HelloWorld.vue'
  4. </script>
  5. <template>
  6. <suspense>
  7. <template #default>
  8. <HelloWorld/>
  9. </template>
  10. <template #fallback>
  11. Loading
  12. </template>
  13. </suspense>
  14. </template>
  • 子组件-helloWold
  1. //子组件 - HelloWorld
  2. <script setup>
  3. import { ref } from 'vue';
  4. const data = ref('');
  5. const load = function() {
  6. return new Promise((resolve) => {
  7. setTimeout(()=>{
  8. data.value = 'hello'
  9. resolve('hello')
  10. }, 3000)
  11. })
  12. }
  13. await load();
  14. </script>
  15. <template>
  16. {{data}}
  17. </template>

关键点:await将setup隐性添加了一个async的关键字,也就是 Promise的返回

注意事项

1.使用要点:子组件的加载方式为异步加载 ,或者子组件的setup应返回一个Promise,async关键字为隐性的Promise返回。 

Teleport【传送】

远距离传送,  可以将teleport内的element移到组件外的特定位置。

官方说明:Teleport 提供了一种干净的方法,允许我们控制在 DOM 中哪个父节点下渲染了 HTML,而不必求助于全局状态或将其拆分为两个组件。

优点:添加组件的灵活性,原先由于布局、层级等原因【类似按钮和触发弹窗等】,需要拆分到不同位置【不同组件】的相关联操作,也可以更好的封装起来。

props:【官方摘要

  1. to - string。必填,必须是有效的查询选择器或 HTMLElement (如果在浏览器环境中使用)。指定将在其中移动 <teleport> 内容的目标元素
  2. disabled - boolean。可选,此属性可用于禁用 <teleport> 的功能,这意味着其插槽内容将不会移动到任何位置,而是在你在周围父组件中指定了 <teleport> 的位置渲染。

实例: 实现一个点击按钮做 inx++,并展示出inx的功能。

vue2实现

  1. <template>
  2. <div class="pager">
  3. <div class="pager__left">
  4. <button @click="inx++">click</button>
  5. </div>
  6. <div class="pager__right">
  7. {{inx}}
  8. </div>
  9. </div>
  10. </template>

vue3-teleport 实现

  • 方案一:同层级的组件传送

  1. //父組件
  2. <template>
  3. <Pager />
  4. <PagerButton/>
  5. </template>
  6. //子組件 - Pager
  7. <template>
  8. <div class="pager">
  9. <div class="pager__left"></div>
  10. <div class="pager__right"></div>
  11. </div>
  12. </template>
  13. //子組件 - PagerButton
  14. <template>
  15. <teleport to=".pager__left">
  16. <button @click="inx++">click</button>
  17. </teleport>
  18. <teleport to=".pager__right">
  19. <span>{{inx}}</span>
  20. </teleport>
  21. </template>

注意:同层级的挂载渲染从上而下,故PagerButton应放在Pager上方。

  • 方案二:不同层级的组件传送【父传子】

  1. //父组件
  2. <template>
  3. <Pager />
  4. <teleport to=".pager__left">
  5. <button @click="inx++">click</button>
  6. </teleport>
  7. <teleport to=".pager__right">
  8. <span>{{inx}}</span>
  9. </teleport>
  10. </template>

注意事项

1.传送目标组件应先挂载好。而同一组件内,挂载顺序是,子组件先挂载完,父组件后挂载,故子组件要挂载到父组件是行不通的,会报warning。如果实在是有这方面的需求,延迟延迟子组件的渲染,也可以【onMounted + v-if】。

传送方向:父 传 子, 后 传 前。

或者若是在index.html上开辟一块地来挂载特殊的东西,也未尝不可。

2.挂载只是移动的过程,而不是销毁和重建的过程哦。

总结

目前这个例子看起来,代码量变大的样子,但是如果pager__left 和pager__right,原先就有大量的代码逻辑呢?或者我们需要对一些组件【例如:tooltip】进行统一管理的时候,teleport可能是个不错的选择。

声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号