Vue3.0来了,来看看有哪些改变

2022-08-02 11:27:37

2020年10月,Vue 3.0终于发布了第一个beta版本,这个大版本更新相较于2.0的推出已经过去两三年了,在前端开发这个快速迭代的大环境下,这么长时间才更新一个大版本挺少见的。但是我得说,虽然三年没有更新大版本,但尤雨溪这三年可真没闲着,三年不开张,一开张就来了个大招。Vue3.0是一套组合拳,它带来的变化全面而繁杂。接下来的2021年,使用Vue2.0的小伙伴们又有新东西要学习了。

那么今天我们就来梳理一下,看看Vue3.0到底有哪些值得关注的改变。

一、Vue生态环境变化。

我们先从Vue的整个生态说起,除了Vue核心库,Vue周边配套也全都来了个大升级,VueRouter,Vuex都升级到了4.0,构建工具也有更新,尤大大自己开发了一个专门的构建工具,叫Vite。这个构建工具尤其值得一说,我认为它弄不好会是webpack的终结者。我们来看看作者的介绍:“Vite,一个基于浏览器原生 ES imports 的开发服务器。利用浏览器去解析 imports,在服务器端按需编译返回,完全跳过了打包这个概念,服务器随起随用。同时不仅有 Vue 文件支持,还搞定了热更新,而且热更新的速度不会随着模块增多而变慢。针对生产环境则可以把同一份代码用 rollup 打包。虽然现在还比较粗糙,但这个方向我觉得是有潜力的,做得好可以彻底解决改一行代码等半天热更新的问题。”

设计目标。

说完生态,我们还是回到Vue核心库,我们最关心的,其实还是这个。先来看下 ** Vue3.0 的6个设计目标:**

  1. 更小:全局 API 和内置组件 / 功能支持 tree-shaking; 常驻的代码尺寸控制在 10kb gzipped 上下。

  2. 更快:基于 Proxy 的变动侦测,性能整体优于 getter / setter;Virtual DOM 重构;编译器架构重构,更多的编译时优化。

  3. 加强 API 设计一致性:3.0的api会更符合人的习惯,更友好

  4. 加强 TypeScript 支持:3.0 本身用 TypeScript 重写,内置 typing;支持TSX;但是不会影响不使用Typescript的用户。另外还有一件很重要的事情,Class API提案已经撤销了,使用TS开发Vue的小伙伴要注意下了。

  5. 提高自身可维护性

  6. 开放更多底层功能

总体的设计目标简单说就是更小更快更友好。。。

二、API变化。

Vue3.0的API变化,总的来说有以下几个需要注意的特点:

  • 技能升级曲线平滑。掌握Vue 2的人应该可以很顺利的使用Vue 3

  • 不能直接把项目从Vue 2升级到Vue 3,因为很多API细节有破坏性修改

  • Vue2的组件库不能直接给Vue3使用

  • 浏览器兼容方面,只兼容到IE11+。呃,这样也好,希望能对IE退出历史舞台再出一份力。

  • 模板语法的 99% 将保持不变。

  • 现有的Options API没有大的变化。

下面我们看下API变化的几个主要方面(API变化很繁杂,此处我们仅列举较常用的API变化):

全局 API 的变化:

Vue 2.x 有许多全局 API 和配置,这些 API 和配置可以全局改变 Vue 的行为。例如,要创建全局组件,可以使用 Vue.component 这样的 API。虽然这种声明方式很方便,但它也会导致一些问题。从技术上讲,Vue 2 没有“app”的概念,我们定义的应用只是通过 new Vue() 创建的根 Vue 实例。从同一个 Vue 构造函数创建的每个根实例 共享相同的全局配置,因此它不利于测试,也不利于在全局多个app之间共享Vue副本。调用 createApp 返回一个应用实例,这是 Vue 3 中的新概念

import{ createApp}from'vue'const app=createApp({})

任何全局改变 Vue 行为的 API 现在都会移动到

应用实例上,以下是当前全局 API 及其相应实例 API 的表:

2.x 全局 API3.x 实例 API ( app )
Vue.configapp.config
Vue.config.productionTipremoved
Vue.config.ignoredElementsapp.config.isCustomElement
Vue.componentapp.component
Vue.directiveapp.directive
Vue.mixinapp.mixin
Vue.useapp.use

模板语法变化

  • Vue 3 中,组件现在正式支持多根节点组件

  • v-if 与 v-for 的优先级对比,两者作用于同一个元素上时, v-if 会拥有比 v-for 更高的优先级

  • 过滤器。过滤器已删除,不再支持。建议用方法调用或计算属性替换它们

  • 按键修饰符,不再支持使用数字 (即键码) 作为 v-on 修饰符,不再支持 config.keyCodes

新增的两个内置组件 Teleport 和 Suspense

Teleport(传入)Teleport 提供了一种干净的方法,允许我们控制在 DOM 中哪个父节点下呈现 HTML,而不必求助于全局状态或将其拆分为两个组件,从此后某个组件创建的Html将可能不在本组件内。想像一下,你要写一个弹窗组件,而你希望这个弹窗组件的html放在body下,那可以使用Teleport方便地实现它

<template><button@click="modalOpen = true">Open full screen modal! (With teleport!)</button><teleportto="body"><divv-if="modalOpen"class="modal"><div>
        I'm a teleported modal! (My parent is "body")<button@click="modalOpen = false">
          Close</button></div></div></teleport></template>
<script>exportdefault{data(){return{
      modalOpen:false,};},};</script>

Suspense

Suspense含义:悬念; 悬而未决,含糊不定; 焦虑,挂念; 中止,暂停,悬停

它是从React借鉴过来的一个概念,Suspense主要解决的就是网络IO问题。网络IO问题其实就是我们现在用Redux+saga等等一系列乱七八糟的库来解决的「副作用」问题。现在Vue3.0实现了Suspense组件,我们可以用它来处理一些异步问题。比如,我们可以用它来处理异步组件的加载状态显示。看下边的例子

<template><divid="app"><divv-if="error">{{ error }}</div><Suspensev-else><template#default><User/></template><template#fallback> Loading...</template></Suspense></div></template>
<script>import Userfrom'@/components/User.vue';import{ onErrorCaptured, ref}from'vue';exportdefault{
  components:{
    User,},setup(){const error=ref(null);onErrorCaptured((e)=>{
      error.value= e;// 不对错误进行拦截returntrue;});return{ error};},};</script>

三、新增的Composition API

我认为Vue3.0核心库变化最大的就是这个Composition API了。它翻译为组合API,组合API是相对于Vue2.x的选项API而言的。

Composition API的设计目的,是为了更好的实现组件间的代码复用。在Vue中,实现页面中代码复用的工具是组件,但用了组件后,你会发现组件间其实也有大量的代码是重复的(比如多个组件都需要相同的权限校验逻辑),需要抽离出来做个封装以便复用。在Vue2.x中,官方给出的解决方案就是Mixins,但Mixins也有很多缺点,比如当你在组件中调用了Mixins中的方法时,你不容易找到这个方法的来源。因此在Vue3.0中,官方给出了一个全新的解决方案,就是Composition API。它最主要的特点是使用功能来组织代码,而不是以选项来组织代码,使用它可以让我们方便的把一个功能相关的所有代码(包括data、methods、computed、watch、生命周期函数等)封装在一个类文件中。

那么接下来我们来看一下,如何把原来选项api中的所有内容,写在一个功能文件中。 Composition API使用起来也并不复杂,你只需要注意以下几个部分:

setup 组件选项,一个可以实际使用Composition API的地方,关于它你只需知道以下三点:

  1. 它实际上是Vue一个新的生命周期函数,在beforeCreate和created之间执行。

  2. 在setup中this无法使用。由于在执行 setup 时尚未创建组件实例,因此在 setup 选项中没有 this 。这意味着, 除了 props 之外,你将无法访问组件中声明的任何属性——本地状态、计算属性或方法。

  3. 可以使用setup函数的两个参数props, context来替代this的使用。

exportdefault{
  props:{
    msg:{
      type: String,default:()=>{}}},setup(props, context){
    console.log(props)// 此处返回props定义的属性// setup()的第二个参数是一个上下文对象,这个上下文对象大致包含了这些属性
    context.attrs
    context.slots
    context.parent
    context.root
    context.emit
    context.refs// Attribute (非响应式对象)
    console.log(context.attrs)// 插槽 (非响应式对象)
    console.log(context.slots)// 触发事件 (方法)
    console.log(context.emit)}}

响应式变量 ref 或 reactive

reactive是用来创建一个响应式对象,等价于2.x的Vue.observable,

ref()函数用来给定的值创建一个响应式的数据对象,ref()的返回值是一个对象,这个对象上只包含一个.value属性。看下边创建一个响应式数据的例子:

import{ ref}from'vue';exportdefault{setup(){const value=ref(1);return{
           value,
           msg:'hello world!'};}};
<template><p>
        {{ value }} {{ msg }}</p></template>

watch 响应式更改

就像我们如何使用 watch 选项在组件内的 user property 上设置侦听器一样,我们也可以 使用从 Vue 导入的 watch 函数执行相同的操作。它接受 3 个参数:

  • 一个响应式引用或我们想要侦听的 getter 函数

  • 一个回调

  • 可选的配置选项

下面是一个例子

import{ ref, watch}from'vue'const counter=ref(0)watch(counter,(newValue, oldValue)=>{  
  console.log('The new counter value is: '+ counter.value)})

与 ref 和 watch 类似,也可以使用从 Vue 导入的 computed 函数在 Vue 组件外部创建计算属性。

生命周期钩子

你可以通过在生命周期钩子前面加上 “on” 来访问组件的生命周期钩子。

下表包含如何在 setup () 内部调用生命周期钩子:

选项 APIHook inside setup
beforeCreateNot needed
createdNot needed
beforeMountonBeforeMount
mountedonMounted
beforeUpdateonBeforeUpdate
updatedonUpdated
beforeUnmountonBeforeUnmount
unmountedonUnmounted
errorCapturedonErrorCaptured
renderTrackedonRenderTracked
renderTriggeredonRenderTriggered

因为 setup 是围绕 beforeCreate 和 created 生命周期钩子运行的,所以不需要显式地定义它们。换句话说,在这些钩子中编写的任何代码都应该直接在 setup 函数中编写。

这些函数接受一个回调函数,当钩子被组件调用时将会被执行:

exportdefault{setup(){// mountedonMounted(()=>{ 
			console.log('Component is mounted!')})}}
  • 作者:深蓝Paul
  • 原文链接:https://blog.csdn.net/weixin_52911883/article/details/111600713
    更新时间:2022-08-02 11:27:37