目录
实例:有一个组件的一些数据需要异步请求,请求完成后再渲染。为了显示优化,我们会在请求返回前显示一个Loading。
实例: 实现一个点击按钮做 inx++,并展示出inx的功能。
前言
阅读vue3源码的时候,发现会根据不同shapeFlag来做不一样的渲染,进而发现了vue3的一些新特性。好吧,我承认这个先后顺序可能有点点反。好了,让我们进入正题吧。
Suspense【试验性,可能变动,生产环境请勿使用】
官方说明:在正确渲染组件之前进行一些异步请求是很常见的事。suspense允许将等待过程提升到组件树中处理,而不是在单个组件中。
实例:有一个组件的一些数据需要异步请求,请求完成后再渲染。为了显示优化,我们会在请求返回前显示一个Loading。
进入页面,显示 Loading,3秒后,显示为 Hello
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:【官方摘要】
to
-string。必填
,必须是有效的查询选择器或 HTMLElement (如果在浏览器环境中使用)。指定将在其中移动<teleport>
内容的目标元素disabled
-boolean
。可选,此属性可用于禁用<teleport>
的功能,这意味着其插槽内容将不会移动到任何位置,而是在你在周围父组件中指定了<teleport>
的位置渲染。
实例: 实现一个点击按钮做 inx++,并展示出inx的功能。
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 应该可以改善这一状态。