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” 的假设,这不仅有学习成本,而且有实现成本!建议用方法调用或计算属性去替换过滤器。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
Vue.js是一种流行的JavaScript框架,用于构建用户界面。Vue 2和Vue 3是Vue.js的两个主要版本,它们之间有一些重要的区别。下面是关于Vue 2和Vue 3转换的一些介绍: 1. 响应性系统:Vue 2使用基于Object.defineProperty的响应式系统来追踪数据的变化。而Vue 3使用Proxy来实现响应式系统,这使得追踪数据变化更加高效和灵活。 2. 组合式API:Vue 3引入了组合式API,这是一种新的API风格,可以更好地组织和重用组件逻辑。相比之下,Vue 2主要使用选项式API。 3. 性能优化:Vue 3在性能方面进行了一些改进,包括更好的树摇动优化、编译器优化和更小的包大小。这些改进使得Vue 3在运行时性能方面比Vue 2更好。 4. TypeScript支持:Vue 3对TypeScript的支持更加友好,包括更好的类型推断和类型定义。Vue 2也支持TypeScript,但Vue 3在这方面有更多的改进。 5. 其他改进:Vue 3还引入了一些其他改进,如Teleport(原名Portal)组件、Suspense组件、Fragment组件等,这些改进可以提供更好的开发体验和更灵活的组件结构。 如果你想将现有的Vue 2项目迁移到Vue 3,你需要注意以下几点: 1. 了解Vue 3的新特性和改变,以便适应新的API和语法。 2. 检查和更新你的代码,确保它在Vue 3能够正常工作。特别是需要注意的是响应式系统的改变和组合式API的使用。 3. 更新相关的依赖项,如Vue Router和Vuex等,以确保它们与Vue 3兼容。 4. 迁移过程,可以使用Vue 2和Vue 3之间的适配器库,如vue-demi,来简化迁移过程。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值