Vue3中令人兴奋的新功能
在上一篇文章中,我们了解了Vue 3将带来的性能改进。我们已经知道用新的Vue编写的应用程序性能炸裂(运行非常好),但性能并不是最重要的部分。对我们开发人员而言最重要的是,新版本将如何影响我们编写代码的方式。
如今,Vue 3带来了许多令人兴奋的新功能。 值得庆幸的是,Vue团队主要介绍了对当前API的添加和改进,而不是进行重大更改,因此,已经了解Vue 2的大家应该会非常习惯这些变化。
让我们从大多数人可能听说过的API开始…
合成API(Composition API)
组合API是Vue的下一个主要版本中最常用的讨论和特色语法。这是一种全新的逻辑重用和代码组织方法。
当前,我们使用所谓的Options API构建组件。现在,添加到Vue组件的逻辑通常会采用:如data
,methods
,computed
等这种方法,最大缺点是这是不JavaScript代码原生方式。您需要确切了解模板中可以访问哪些属性,以及this
关键字的行为。在后台,Vue编译器需要将此属性转换为工作代码。因此,我们无法通过从自动建议或类型检查中受益(而大家想一想Typescript,马上就会明白了)。
Composition API旨在,通过将组件属性中当前可用的机制公开为JavaScript函数来解决此问题。Vue核心团队将Composition API描述为“一组基于功能的附加API,可以灵活地组合组件逻辑”。用Composition API编写的代码更具可读性,并且都是原生JS,这使它更易于阅读和学习。
让我们来看一个使用新的Composition API理解其工作原理的组件的简单示例。
1 | <template> |
现在,让我们将此代码分解为几部分,以了解发生了什么
1 | import { ref, computed, onMounted } from 'vue' |
正如之前提到的,Composition API将组件属性公开为函数,因此第一步是导入所需的函数。当前情况下,我们需要使用创建反应式引用ref
,使用计算属性创建computed
和使用访问生命周期挂钩onMounted
。
现在,你可能想知道这种神秘的setup
方法是什么?
1 | export default { |
简而言之,它只是一个将属性和函数返回到模板的函数,而已。我们在这里声明所有反应性属性、计算属性、观察者和生命周期挂钩,然后将它们返回,以便可以在模板中使用它们。
我们没有从setup
函数返回的内容将在模板中不可用。
1 | const count = ref(0) |
根据以上内容,我们声明了响应式的count
用ref
函数调用,它可以包装任何类型参数或对象,并返回其双向引用,传递的元素的值将保留在value
创建的引用的属性中。例如,如果要访问count
参考值,则需要明确要求count.value
。
1 | const double = computed(() => count.value * 2) |
…这正是我们在声明计算属性double
以及increment
函数时所做的事情。
1 | onMounted(() => console.log('component mounted!')) |
使用onMounted
钩子,我们会在安装组件时记录一些消息。
1 | return { |
最后,我们返回count
和double
属性with increment
方法,以使它们在模板中可用。
1 | <template> |
现在,我们可以访问setup
模板中方法返回的属性和函数,就像通过旧的Options API声明它们一样。
这是一个简单的示例,也可以通过Options API轻松实现。
新的Composition API的修改了编码方式,加强了在重用我们的代码/逻辑时代码块复用性。
使用Composition API进行代码重用
新的Composition API具有更多优点,比如:代码复用。当前,如果我们要在其他组件之间共享一些代码,则有两个可用选项mixins
和作用域插槽
。两者都有缺点。
假设我们要提取counter
功能并将其在其他组件中复用。在下面,您可以看到如何将其与可用的API和新的Composition API结合使用:
让我们从mixins开始:
1 | import CounterMixin from './mixins/counter' |
mixins的最大缺点是:我们对它实际上添加到我们的组件中一无所知。这不仅使推理变得困难,而且还可能导致名称与现有属性和功能发生冲突。
现在该是作用域插槽了。
1 | <template> |
使用作用域插槽,我们确切地知道可以通过v-slot
属性访问哪些属性,因此更容易理解代码。这种方法的缺点是:我们只能在模板中访问它,并且仅在Counter
组件范围内可用。
现在是时候使用Composition API了:
1 | function useCounter() { |
是不是更优雅?我们不受模板和组件范围的限制,并且确切地知道可以从计数器访问哪些属性。另外,我们可以从编辑器中可用的代码完成中受益,因为useCounter
它只是一个返回某些属性的函数。幕后没有魔力,因此编辑器可以帮助我们进行类型检查和建议。
这也是使用第三方库的一种更优雅的方式。例如,如果我们要使用Vuex,则可以显式使用useStore
函数而不是污染Vue原型(this.$store
)。这种方法还可以消除Vue插件的幕后魔力。
1 | const { commit, dispatch } = useStore() |
如果您想了解有关Composition API及其用例的更多信息,我强烈建议您从Vue团队阅读此文档,该文档解释了新API背后的原因并提出了最佳用例。Vue核心团队的ThorstenLünborg 还提供了一个很棒的存储库,其中包含Composition API使用示例。
全局安装/配置API更改
我们可以在实例化和配置应用程序的方式上找到另一个重大变化。让我们看看它现在如何工作:
1 | import Vue from 'vue' |
当前,我们正在使用全局Vue
对象提供任何配置并创建新的Vue实例。对Vue
对象所做的任何更改都会影响每个Vue实例和组件。
现在,让我们看看它如何在Vue 3中运行:
1 | import { createApp } from 'vue' |
您可能已经注意到,每个配置都限于使用定义的某个Vue应用程序createApp
。
它可以使您的代码更易于理解,并且不易出现由第三方插件引起的意外问题。当前,如果某些第三方解决方案正在修改Vue对象,则它可能以意想不到的方式(尤其是全局混合)影响您的应用程序,而Vue 3则无法实现。
当前在此RFC 中讨论了此API更改,这意味着将来可能会更改。
碎片(Fragments)
我们可以在Vue 3中期待的另一个激动人心的附加功能是片段。
您可能会问什么碎片?好吧,如果您创建一个Vue组件,则它只能有一个根节点。
这意味着无法创建这样的组件:
1 | <template> |
原因是代表任何Vue组件的Vue实例都需要绑定到单个DOM元素中。创建具有多个DOM节点的组件的唯一方法是通过创建不具有基础Vue实例的功能组件。
事实证明,React社区也有同样的问题。他们提出的解决方案是一个名为Fragment的虚拟元素。看起来或多或少是这样的;
1 | class Columns extends React.Component { |
即使Fragment看起来像一个普通的DOM元素,它也是虚拟的,根本不会在DOM树中呈现。这样,我们可以将组件功能绑定到单个元素中,而无需创建冗余DOM节点。
当前,您可以在带有vue-fragments库的Vue 2中使用片段,而在Vue 3中,您可以立即使用它!
Suspense组件
React生态系统中另一个将在Vue 3中采用的好主意是Suspense组件。
挂起将挂起组件渲染并渲染回退组件,直到满足条件为止。在Vue London Evan期间,您简短地谈到了这个主题,并向我们展示了我们可以期望的API。事实证明,Suspense只是具有插槽的组件:
1 | <Suspense> |
后备内容将一直显示到Suspended-component
完全渲染为止。挂起可以等待,直到该组件被下载(如果这是一个异步组件),或者在setup
功能上执行一些异步操作。
多个v-model同时使用
v-model
是一种指令,可用于在给定组件上实现双向绑定。我们可以传递反应性属性并从组件内部对其进行修改。
我们v-model
从表单元素非常了解:
1 | <input v-model="property /> |
但是您知道您可以使用v-model
每个组件吗?内幕v-model
只是传递value
属性和侦听input
事件的捷径。将以上示例重写为以下语法将具有完全相同的效果:
1 | <input |
我们甚至可以使用components model
属性更改默认属性和事件的名称:
1 | model: { |
正如上面所示,vue2.x中采用v-model
时,如果我们希望在组件中进行双向绑定,那么伪指令可能是一个非常有用的语法求和者。不幸的是,v-model
每个组件只能有一个组件。
幸运的是,在Vue 3中这不会成为问题!您将能够提供v-model
属性名称,并根据需要拥有任意数量的属性。在下面,您可以v-model
在表单组件中找到两个的示例:
1 | <InviteeForm |
当前在此RFC 中讨论了此API更改,这意味着将来可能会更改。
Portals组件(魔法提示类组件)
Portals是特殊的组件,旨在在当前组件之外呈现某些内容。这也是React本身实现的功能之一(https://pl.reactjs.org/docs/portals.html)。这就是React文档关于门户的内容:
“Portals provide a first-class way to render children into a DOM node that exists outside the DOM hierarchy of the parent component.“
这是处理模态框、弹出窗口和通常显示在页面顶部的组件的一种非常好的方法。通过使用Portals,您可以确保没有任何主机组件CSS规则,会影响您要显示的组件,并使您免于使用进行讨厌的黑客攻击z-index
。
对于每个门户,我们需要指定它的目标目标,在其中将呈现提示类型内容。在下面,您可以看到portal-vue库的实现,该实现将此功能添加到Vue 2:
1 | <portal to="destination"> |
Vue 3将附带对门户的开箱即用支持!
新的自定义指令API
自定义指令API在Vue 3中将略有变化,以更好地与组件生命周期保持一致。这项更改将使API更加直观,从而使新手更容易理解和学习API。
这是当前的自定义指令API:
1 | const MyDirective = { |
……这就是Vue 3中的样子。
1 | const MyDirective = { |
即使这是一项重大更改,也应该使用Vue兼容性构建轻松涵盖。
当前在此RFC 中讨论了此API更改,这意味着将来可能会更改。
摘要
除了Composition API(它是Vue 3中最大的主要新API)之外,我们还可以找到很多较小的改进。我们可以看到,Vue正在朝着更好的开发人员体验和更简单,更直观的API迈进。也很高兴看到Vue团队决定采用许多想法,而这些想法目前只能通过第三方库提供给框架的核心。
上面的列表仅表示主要的API更改和改进。如果您对其他应用程序感到好奇,可以看一下Vue RFCs存储库。。