vue3新特性-Suspense和Teleport

目录

前言

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

实例:有一个组件的一些数据需要异步请求,请求完成后再渲染。为了显示优化,我们会在请求返回前显示一个Loading。

vue2实现

vue3-suspense 实现

注意事项

Teleport【传送】

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

vue2实现

vue3-teleport 实现

注意事项

总结


前言

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

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

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

实例:有一个组件的一些数据需要异步请求,请求完成后再渲染。为了显示优化,我们会在请求返回前显示一个Loading。

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

vue3新特性-Suspense和Teleport

vue2实现

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

<template>
  <div class="pager">
    <div v-if="loading">Loading</div>
    <div v-else>{{data}}</div>
  </div>
</template>
<script>
  export default {
    data() {
      return {
        loading: true,
        data: ''
      }
    },
    created() {
      this.load();
    },
    methods: {
      load() {
        this.loading = true;
        return new Promise((resolve) => {
		  setTimeout(()=>{
		    this.data= 'hello'
            this.loading = false;
			resolve('hello')
		  }, 3000)
	   })
      }
    }
  }
</script>

vue3-suspense 实现

  • 父组件
//父组件

<script setup>
import HelloWorld from './components/HelloWorld.vue'
</script>

<template>
	<suspense>
	  <template #default>
	    <HelloWorld/>
	  </template>
	  <template #fallback>
			Loading
		</template>
	</suspense>
</template>
		
  • 子组件-helloWold
//子组件 - HelloWorld

<script setup>
import { ref } from 'vue';
const data = ref('');

const load = function() {
	return new Promise((resolve) => {
		setTimeout(()=>{
			data.value = 'hello'
			resolve('hello')
		}, 3000)
	})
}

await load(); 

</script>

<template>
  {{data}}
</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的功能。

vue3新特性-Suspense和Teleport

vue2实现

<template>
  <div class="pager">
    <div class="pager__left">
      <button @click="inx++">click</button>
    </div>
    <div class="pager__right">
      {{inx}}
    </div>
  </div>
</template>

vue3-teleport 实现

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

//父組件
<template>
	<Pager />
	<PagerButton/>
</template>

//子組件 - Pager 
<template>
	<div class="pager">
	    <div class="pager__left"></div>
	    <div class="pager__right"></div>
	 </div>
</template>

//子組件 - PagerButton
<template>
  <teleport to=".pager__left">
	  <button @click="inx++">click</button>
  </teleport>
  <teleport to=".pager__right">
	 <span>{{inx}}</span> 
  </teleport>
</template>

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

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

//父组件
<template>
	<Pager />
	<teleport to=".pager__left">
		  <button @click="inx++">click</button>
	</teleport>
	<teleport to=".pager__right">
		 <span>{{inx}}</span> 
	</teleport>
</template>

注意事项

1.传送目标组件应先挂载好。而同一组件内,挂载顺序是,子组件先挂载完,父组件后挂载,故子组件要挂载到父组件是行不通的,会报warning

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

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

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

总结

目前这个例子看起来,代码量变大的样子,但是如果pager__left 和pager__right,原先就有大量的代码逻辑呢?原vue2的mixins可以功能性拆分,但是template的页面布局就没有那么方便了,目前vue3的 mixins + teleport 应该可以改善这一状态。

上一篇:实用的vue2.x与vue3,x的代码片段


下一篇:5-3 Linux内核计时、延时函数与内核定时器【转】