您现在的位置是:首页 >学无止境 >Vue3技术8之Fragment、Suspense、Vue3中其他的改变网站首页学无止境

Vue3技术8之Fragment、Suspense、Vue3中其他的改变

VillanelleS 2023-06-13 00:00:03
简介Vue3技术8之Fragment、Suspense、Vue3中其他的改变

Fragment

  1. 在Vue2中:组件必须有一个根标签
  2. 在Vue3中:组件可以没有根标签,内部会将多个标签包含在一个Fragment虚拟元素中
  3. 好处:减少标签层级,减少内存占用
    在这里插入图片描述

Teleport

弹窗案例

目录结构

在这里插入图片描述

App.vue

<template>
  <div class="app">
    <h1>我是App组件</h1>
    <Child></Child>
  </div>
</template>

<script>
import Child from "@/components/Child";

export default {
  name: 'App',
  components: {Child},
}
</script>

<style scoped>
.app{
  background-color: gray;
  padding: 10px;
}
</style>

Child.vue

<template>
  <div class="child">
    <h1>我是Child组件</h1>
    <Son></Son>
  </div>
</template>

<script>
import Son from "@/components/Son";
export default {
    name: "Child",
  components: {Son}
}
</script>

<style scoped>
.child{
  background-color: orange;
  padding: 10px;
}
</style>

Son.vue

<template>
  <div class="son">
    <h1>我是Son组件</h1>
    <Dialog></Dialog>
  </div>
</template>

<script>
import Dialog from "@/components/Dialog";
export default {
  name: "Son",
  components: {Dialog},
}
</script>

<style scoped>
.son{
  background-color: pink;
  padding: 10px;
}
</style>

Dialog.vue

<template>
  <div>
    <button @click="isShow=true">点我弹个窗</button>
    <teleport to="body">
      <div class="mask"  v-if="isShow">
        <div class="dialog">
          <h3>我是一个弹窗</h3>
          <h4>一些内容</h4>
          <h4>一些内容</h4>
          <h4>一些内容</h4>
          <button @click="isShow=false">关闭弹窗</button>
        </div>
      </div>
    </teleport>
  </div>
</template>

<script>
import {ref} from "vue";

export default {
    name: "Dialog",
  setup(){
      let isShow=ref(false)
    return{
        isShow
    }
  },
}
</script>

<style scoped>
.mask{
  position: absolute;
  top: 0;bottom: 0;left: 0;right: 0;
  background-color: rgba(0,0,0,0.5);
}
.dialog{
  width: 300px;
  height: 300px;
  background-color: skyblue;
  text-align: center;
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%,-50%);
}
</style>

请添加图片描述

总结

  1. 什么是Teleport?——Teleport是一种能将我们的组件html结构移动到指定位置的技术
<teleport to="移动位置">
	<div v-if="isShow" class="mask">
		<div class="dialog">
			<h3>我是一个弹窗</h3>
			<button @click="isShow=false">关闭弹窗</button>
		</div>
	</div>
</teleport>

Suspense

普通写法

App组件和Child组件是一起加载出来的

App.vue

<template>
  <div class="app">
    <h1>我是App组件</h1>
    <Child></Child>
  </div>
</template>

<script>
import Child from "@/components/Child";  //静态引入

export default {
  name: 'App',
  components: {Child},
}
</script>

<style scoped>
.app{
  background-color: gray;
  padding: 10px;
}
</style>

Child.vue

<template>
  <div class="child">
    <h1>我是Child组件</h1>
  </div>
</template>

<script>
export default {
    name: "Child",
}
</script>

<style scoped>
.child{
  background-color: orange;
  padding: 10px;
}
</style>

请添加图片描述

使用suspense之后

App.vue

<template>
  <div class="app">
    <h1>我是App组件</h1>
    <suspense>
      <template v-slot:default>
        <Child></Child>
      </template>
      <template v-slot:fallback>
        <h3>稍等,加载中...</h3>
      </template>
    </suspense>
  </div>
</template>

<script>
// import Child from "@/components/Child";  //静态引入
import {defineAsyncComponent} from 'vue'
const Child=defineAsyncComponent(()=>import('@/components/Child'))  //异步引入
export default {
  name: 'App',
  components: {Child},
}
</script>

<style scoped>
.app{
  background-color: gray;
  padding: 10px;
}
</style>

Child.vue

<template>
  <div class="child">
    <h1>我是Child组件</h1>
  </div>
</template>

<script>
export default {
    name: "Child",
}
</script>

<style scoped>
.child{
  background-color: orange;
  padding: 10px;
}
</style>

请添加图片描述

不再自己调整网络低速

Child.vue

<template>
  <div class="child">
    <h1>我是Child组件</h1>
    <div>{{sum}}</div>
  </div>
</template>

<script>
import {ref} from "vue";

export default {
    name: "Child",
  async setup(){
      let sum=ref(0)
      const p=  new Promise((resolve, reject) => {
        setTimeout(() => {
          resolve({sum})
        },3000)
      })
    return await p
  }
}
</script>

<style scoped>
.child{
  background-color: orange;
  padding: 10px;
}
</style>

App.vue

<template>
  <div class="app">
    <h1>我是App组件</h1>
    <suspense>
      <template v-slot:default>
        <Child></Child>
      </template>
      <template v-slot:fallback>
        <h3>稍等,加载中...</h3>
      </template>
    </suspense>
  </div>
</template>

<script>
// import Child from "@/components/Child";  //静态引入
import {defineAsyncComponent} from 'vue'
const Child=defineAsyncComponent(()=>import('@/components/Child'))  //异步引入
export default {
  name: 'App',
  components: {Child},
}
</script>

<style scoped>
.app{
  background-color: gray;
  padding: 10px;
}
</style>

总结

补充setup的一个知识点

  1. setup不能是一个async函数,因为返回值不再是return的对象,而是promise,模板看不到return对象中的属性。(后期也可以返回一个Promise实例,但需要Suspense和异步组件的配合)

Suspense总结

  1. 等待异步组件时渲染一些额外内容,让应用有更好的用户体验
  2. 使用步骤
    (1)异步引入组件
import {defineAsyncComponent} from 'vue'
const Child=defineAsyncComponent(()=>import('@/components/Child'))  //异步引入

(2)使用Suspense包裹组件,并配置好defaultfallback

<template>
  <div class="app">
    <h1>我是App组件</h1>
    <suspense>
      <template v-slot:default>
        <Child/>
      </template>
      <template v-slot:fallback>
        <h3>稍等,加载中...</h3>
      </template>
    </suspense>
  </div>
</template>

Vue3中其他的改变

全局API的转移

  1. Vue 2.x 有许多全局 API 和配置。
    例如:注册全局组件、注册全局指令等
//注册全局组件
    Vue.component('MyButton', {
      data: () => ({
        count: 0
      }),
      template: '<button @click="count++">Clicked {{ count }} times.</button>'
    })
    
    //注册全局指令
    Vue.directive('focus', {
      inserted: el => el.focus()
    }
  1. Vue3中对这些API做了调整
    将全局的API,即:Vue.xxx调整到应用实例(app)

    2.x 全局 API(Vue3.x 实例 API (app)
    Vue.config.xxxxapp.config.xxxx
    Vue.config.productionTip移除
    Vue.componentapp.component
    Vue.directiveapp.directive
    Vue.mixinapp.mixin
    Vue.useapp.use
    Vue.prototypeapp.config.globalProperties

其他改变

  1. data选项应始终被声明为一个函数。
  2. 过度类名的更改:
  • Vue2.x写法

    .v-enter,
    .v-leave-to {
      opacity: 0;
    }
    .v-leave,
    .v-enter-to {
      opacity: 1;
    }
    
  • Vue3.x写法

    .v-enter-from,
    .v-leave-to {
      opacity: 0;
    }
    
    .v-leave-from,
    .v-enter-to {
      opacity: 1;
    }
    
  1. 移除keyCode作为 v-on 的修饰符,同时也不再支持config.keyCodes
  2. 移除修饰符
  • 父组件中绑定事件

    <my-component
      v-on:close="handleComponentEvent"
      v-on:click="handleNativeClickEvent"
    />
    
  • 子组件中声明自定义事件

    <script>
      export default {
        emits: ['close']
      }
    </script>
    
  1. 移除过滤器(filter)

过滤器虽然这看起来很方便,但它需要一个自定义语法,打破大括号内表达式是 “只是 JavaScript” 的假设,这不仅有学习成本,而且有实现成本!建议用方法调用或计算属性去替换过滤器。

风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。