Vue 3中令人兴奋的新功能 由Filip Rakowski撰写

我们已经知道用新的主要版本Vue编写的应用程序性能会很好,但是性能并不是最重要的部分。对我们开发人员而言最重要的是,新版本将如何影响我们编写代码的方式。

如您所料,Vue 3带来了许多令人兴奋的新功能。 值得庆幸的是,Vue团队主要介绍了对当前API的添加和改进,而不是进行重大更改,因此,已经了解Vue 2的人们应该很快对新语法感到满意。

让我们从大多数人可能听说过的API开始…

合成API

组合API是Vue的下一个主要版本中最常用的讨论和特色语法。这是一种全新的逻辑重用和代码组织方法。

当前,我们使用所谓的Options API来构建组件。要添加到逻辑组件的Vue我们填充(可选),如性能data,methods,computed等这种方法的最大缺点是事实,这是不工作的JavaScript代码本身。您需要确切了解模板中可以访问哪些属性以及this关键字的行为。在后台,Vue编译器需要将此属性转换为工作代码。因此,我们无法从自动建议或类型检查中受益。

Composition API旨在通过将组件属性中当前可用的机制公开为JavaScript函数来解决此问题。Vue核心团队将Composition API描述为“一组基于功能的附加API,可以灵活地组合组件逻辑”。用Composition API编写的代码更具可读性,并且幕后没有魔力,使阅读和学习变得更容易。

让我们看一个使用新的Composition API理解其工作原理的组件的简单示例。

<template>
  <button @click="increment">
    Count is: {{ count }}, double is {{ double }}, click to increment.
  </button>
</template>

<script>
import { ref, computed, onMounted } from 'vue'

export default {
  setup() {
    const count = ref(0)
    const double = computed(() => count.value * 2)

    function increment() {
      count.value++
    }

    onMounted(() => console.log('component mounted!'))

    return {
      count,
      double,
      increment
    }
  }
}
</script>

现在,让我们将此代码分解为几部分,以了解发生了什么

import { ref, computed, onMounted } from 'vue'

正如我之前提到的,Composition API将组件属性公开为函数,因此第一步是导入所需的函数。在我们的案例中,我们需要使用创建反应式引用ref,使用计算属性,使用computed访问访问生命周期挂钩onMounted。

现在您可能想知道这种神秘的setup方法是什么?

export default {
  setup() {

简而言之,它只是一个将属性和函数返回到模板的函数。就是这样。我们在这里声明所有反应性属性,计算属性,观察者和生命周期挂钩,然后将它们返回,以便可以在模板中使用它们。

我们没有从setup函数返回的内容将在模板中不可用。

const count = ref(0)

根据上面的内容,我们声明了count用ref函数调用的反应性。它可以包装任何原语或对象并返回其反应性引用。传递的元素的值将保留在value创建的引用的属性中。例如,如果要访问count参考值,则需要明确要求count.value。

const double = computed(() => count.value * 2)

function increment() {
  count.value++
}

…这正是我们在声明计算属性double以及increment函数时所做的事情。

onMounted(() => console.log('component mounted!'))
使用onMounted钩子,我们会在安装组件时记录一些消息,只是向您展示您可以😉

return {
  count,
  double,
  increment
}

最后,我们将返回count和double属性withincrement方法,以使它们在模板中可用。

<template>
  <button @click="increment">
    Count is: {{ count }}, double is {{ double }}. Click to increment.
  </button>
</template>

瞧!现在,我们可以访问setup模板中方法返回的属性和函数,就像通过旧的Options API声明它们一样。

这是一个简单的示例,也可以通过Options API轻松实现。新的Composition API的真正好处不仅在于以不同的方式进行编码,而且在重用我们的代码/逻辑时,这些好处也能显示出来。

使用Composition API进行代码重用

新的Composition API具有更多优点。考虑一下代码重用。当前,如果我们要在其他组件之间共享一些代码,则有两个可用选项-mixins和作用域插槽。两者都有其缺点。

假设我们要提取counter功能并将其在其他组件中重用。在下面,您可以看到如何将其与可用的API和新的Composition API结合使用:

让我们从mixins开始:

import CounterMixin from './mixins/counter'

export default {
  mixins: [CounterMixin]
}

mixins的最大缺点是我们对它实际上添加到我们的组件中一无所知。这不仅使推理变得困难,而且还可能导致名称与现有属性和功能发生冲突。

现在该是作用域插槽了。

<template>
  <Counter v-slot="{ count, increment }">
     {{ count }}
    <button @click="increment">Increment</button> 
  </Counter> 
</template>

使用作用域插槽,我们确切地知道可以通过v-slot属性访问哪些属性,因此更容易理解代码。这种方法的缺点是我们只能在模板中访问它,并且仅在Counter组件范围内可用。

现在是时候使用Composition API了:

function useCounter() {
  const count = ref(0)
  function increment () { count.value++ }

  return {
    count,
    incrememt
  }
}

export default {
  setup () {
    const { count, increment } = useCounter()
    return {
      count,
      increment
    }
  }
}

是不是更优雅?我们不受模板和组件范围的限制,并且确切地知道我们可以从计数器访问哪些属性。另外,我们可以从编辑器中可用的代码完成中受益,因为useCounter它只是一个返回某些属性的函数。幕后没有魔力,因此编辑器可以帮助我们进行类型检查和建议。

这也是使用第三方库的一种更优雅的方式。例如,如果我们要使用Vuex,则可以显式使用useStore函数,而不是污染Vue原型(this.$store)。这种方法也消除了Vue插件的幕后魔力。

const { commit, dispatch } = useStore()

如果您想了解有关Composition API及其用例的更多信息,我强烈建议您从Vue团队阅读此文档,其中解释了新API背后的原因并提出了最佳用例。Vue核心团队的ThorstenLünborg还提供了一个很棒的存储库,其中包含Composition API使用示例。

全局安装/配置API更改
我们可以在实例化和配置应用程序的方式中找到另一个重大变化。让我们看看它现在是如何工作的:

import Vue from 'vue'
import App from './App.vue'

Vue.config.ignoredElements = [/^app-/]
Vue.use(/* ... */)
Vue.mixin(/* ... */)
Vue.component(/* ... */)
Vue.directive(/* ... */)

new Vue({
  render: h => h(App)
}).$mount('#app')

当前,我们正在使用全局Vue对象来提供任何配置并创建新的Vue实例。对Vue对象所做的任何更改都会影响每个Vue实例和组件。

现在,让我们看看它如何在Vue 3中运行:

import { createApp } from 'vue'
import App from './App.vue'

const app = createApp(App)

app.config.ignoredElements = [/^app-/]
app.use(/* ... */)
app.mixin(/* ... */)
app.component(/* ... */)
app.directive(/* ... */)

app.mount('#app')

您可能已经注意到,每个配置都限于使用定义的某个Vue应用程序createApp。

它可以使您的代码更易于理解,并且不易出现由第三方插件引起的意外问题。当前,如果某些第三方解决方案正在修改Vue对象,则它可能以意想不到的方式(尤其是全局混合)影响您的应用程序,而Vue 3则无法实现。

当前在此RFC中讨论了此API更改,这意味着将来可能会更改。

碎片
我们可以在Vue 3中期待的另一个激动人心的附加功能是片段。

您可能会问什么片段?好吧,如果您创建一个Vue组件,则它只能有一个根节点。

这意味着无法创建这样的组件:

<template>
  <div>Hello</div>
  <div>World</div>
</template>

这样做的原因是代表任何Vue组件的Vue实例都需要绑定到单个DOM元素中。创建具有多个DOM节点的组件的唯一方法是通过创建不具有基础Vue实例的功能组件。

事实证明,React社区也有同样的问题。他们提出的解决方案是一个名为Fragment的虚拟元素。看起来或多或少是这样的;

class Columns extends React.Component {
  render() {
    return (
      <React.Fragment>
        <td>Hello</td>
        <td>World</td>
      </React.Fragment>
    );
  }
}

即使Fragment看起来像一个普通的DOM元素,它也是虚拟的,根本不会在DOM树中呈现。这样,我们可以将组件功能绑定到单个元素中,而无需创建冗余的DOM节点。

当前,您可以在Vue 2中将Fragments与vue-fragments库一起使用,而在Vue 3中,您可以立即使用它!

悬念

React生态系统中另一个将在Vue 3中采用的好主意是Suspense组件。

Suspense暂停您的组件渲染,并渲染后备组件,直到满足条件为止。在Vue London Evan期间,您简短地谈到了这个主题,并向我们展示了我们可以期望的API。事实证明,Suspense只是一个带有插槽的组件:

<Suspense>
  <template >
    <Suspended-component />
  </template>
  <template #fallback>
    Loading...
  </template>
</Suspense>

将显示后备内容,直到Suspended-component完全渲染为止。挂起可以等待,直到该组件被下载(如果这是一个异步组件),或者在setup功能上执行一些异步操作。

多个v模型
V模型是一种指令,可用于在给定组件上实现双向绑定。我们可以传递反应性属性并从组件内部对其进行修改。

我们v-model从表单元素非常了解:

<input v-model="property />

但是您知道您可以使用v-model每个组件吗?内幕v-model只是传递value属性和侦听input事件的捷径。将以上示例重写为以下语法将具有完全相同的效果:

<input 
  v-bind:value="property"
  v-on:input="property = $event.target.value"
/>

我们甚至可以使用componentsmodel属性来更改默认属性和事件的名称:

model: {
  prop: 'checked',
  event: 'change'
}

如您所见,v-model如果我们希望在组件中进行双向绑定,那么伪指令可以是一个非常有用的语法求和者。不幸的是,v-model每个组件只能有一个组件。

幸运的是,在Vue 3中这不会成为问题!您将能够给出v-model属性名称,并根据需要拥有任意数量的属性。在下面,您可以v-model在表单组件中找到两个的示例:

<InviteeForm
  v-model:name="inviteeName"
  v-model:email="inviteeEmail"
/>

当前在此RFC中讨论了此API更改,这意味着将来可能会更改。

门户网站
门户网站是特殊的组件,旨在在当前组件之外呈现某些内容。这也是React本身实现的功能之一。这就是React文档关于门户的内容:

“门户网站可以提供一流的方式来呈现儿童到存在的父组件的DOM层次结构之外的DOM节点。”

这是处理模态,弹出窗口以及通常显示在页面顶部的组件的一种非常好的方法。通过使用门户,您可以确保没有任何主机组件CSS规则会影响您要显示的组件,并且使您免于使用进行讨厌的黑客攻击z-index。

对于每个门户,我们都需要指定其目标位置,在该目​​标位置将呈现门户内容。在下面,您可以看到portal-vue库的实现,该实现将此功能添加到Vue 2:

<portal to="destination">
  <p>This slot content will be rendered wherever thportal-target with name 'destination'
    is  located.</p>
</portal>

<portal-target name="destination">
  <!--
  This component can be located anywhere in your App.
  The slot content of the above portal component wilbe rendered here.
  -->
</portal-target>

Vue 3将附带对门户的开箱即用支持!

新的自定义指令API

自定义指令API在Vue 3中将略有变化,以更好地与组件生命周期保持一致。这项更改将使API更加直观,从而使新手更容易理解和学习API。

这是当前的自定义指令API:

const MyDirective = {
  bind(el, binding, vnode, prevVnode) {},
  inserted() {},
  update() {},
  componentUpdated() {},
  unbind() {}
}

…这就是Vue 3中的样子。

const MyDirective = {
  beforeMount(el, binding, vnode, prevVnode) {},
  mounted() {},
  beforeUpdate() {},
  updated() {},
  beforeUnmount() {}, // new
  unmounted() {}
}

即使这是一项重大更改,也应该使用Vue兼容性构建轻松涵盖它。

当前在此RFC中讨论了此API更改,这意味着将来可能会更改。

转载自Vue school

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值