Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Vue 3.2 有哪些新变化? #109

Open
ljianshu opened this issue Sep 24, 2021 · 0 comments
Open

Vue 3.2 有哪些新变化? #109

ljianshu opened this issue Sep 24, 2021 · 0 comments

Comments

@ljianshu
Copy link
Owner

前言

8.10号凌晨,尤雨溪在微博平台官宣 Vue 3.2 版本正式发布:
image.png

此版本包含一系列重要的新功能与性能改进,但并不涉及任何重大变更。本文主要介绍一些相对重要 Vue3.2新特性,如需了解更多请查阅官方文档!

新的 SFC 功能

关于单文件组件(SFC,即.vue 文件)的两项功能已经由实验状态正式毕业,现提供稳定版本

  • <script setup> 是一种编译时语法糖,能够极大改善在 SFC 中使用 Composition API 时的开发者体验。
  • <style> v-bind 用于在 SFC <style> 标签中启用组件状态驱动的动态 CSS 值。

1、<script setup>

<script setup>中,我们不必声明export defaultsetup方法,这种写法会自动将所有顶级变量、函数,均会自动暴露给模板(template)使用。我们先来通过一个例子,对比script setup前后写法的不同,直观感受下setup带给我们的便利:

// script setup之前的写法
<template>
  <div>
    <div>浪里行舟</div>
    <Card>{{ message }}</Card>
  </div>
</template>
<script lang="ts">
import { ref, defineComponent } from "vue";
import Card from "./components/Card.vue";

export default defineComponent({
  components: {
    Card,
  },
  setup() {
    const message = ref("vue 3.2 新特性 script setup");
    return { message };
  },
});
</script>
// script setup的写法
<template>
  <div>
    <div>浪里行舟</div>
    <Card>{{message}}</Card>
  </div>
</template>

<script lang="ts" setup>
import { ref } from "vue";
import Card from "./components/Card.vue";
const message = ref("vue 3.2 新特性 script setup");
</script>

从上面的例子来看,<script setup>语法省去了组件Card的注册步骤,以及return变量message的语句,使得代码更为精简。关于<script setup>的使用还有些细节和注意事项,我将会在下一篇文章详细介绍。

2、<style> v-bind

挺有趣的一个新特性,通过这个指令,Vue SFC 的 CSS 灵活性将大大提高。该指令适用于<script setup>, 并支持 JavaScript 表达式(必须用引号括起来)。

<script setup>
import { ref } from "vue";
const color = ref("pink");
color.value = "green";
const fontSize = ref("18px");
</script>
<template>
  <h2>浪里行舟</h2>
  <h1>Hello Vue3.2</h1>
  <h2>{{ color }}</h2>
  <button @click="color = 'red'">color red</button>
  <button @click="color = 'yellow'">color yellow</button>
  <button @click="color = 'blue'">color blue</button>
  <button @click="fontSize = '40px'">fontSize 40px</button>
</template>
<style scoped>
h1 {
  color: v-bind(color);
}
h2 {
  font-size: v-bind(fontSize);
}
</style>

1.gif

点击按钮更改color 或者 fontSize的数值,可以看到页面样式也会响应式变化。其原理就是自定义属性将通过内联样式应用于组件的根元素,并在数值更改时进行响应更新。

v-memo

3.2 版本为 Vue 的响应式系统带来了一系列重大性能改进,具体包括:

  • 更高效的 ref 实现(读取速度提高约 260%,写入速度提高约 50%)
  • 依赖项跟踪速度提高约 40%
  • 内存使用量减少约 17%

新版本还提供新的 v-memo 指令,可实现对部分模板树的记忆功能。当v-memo 命中时,不仅允许 Vue 跳过虚拟 DOM 差异、甚至可以完全跳过新 VNode 的创建步骤。虽然这个指令使用频率不高,但它提供了一个逃生舱来在某些情况下(例如处理大型 v-for 列表)获取最大性能。

<div v-for="user of users" :key="user.id" v-memo="[user.name]">
  {{ user.name }}
</div>

这个例子使用v-memo,不会重新创建虚拟元素,并且会重新使用前一个元素,除非v-memo(此处为用户名)的条件发生变化。这可能看起来是一个很小的改进,但如果您渲染大量元素,它实际上是性能的巨大改进。

其实v-memo可以接受一组条件,请看下面的例子:

<div v-for="user of users" :key="user.id" v-memo="[user.name, selectedUserId === user.id]">
  <p :class="{ red: selectedUserId === user.id }">{{ user.name }}</p>
</div>

此时如果user.nameselectedUserId发生变化,div则将更新。

新 ref 语法糖(实验性)

$ref()避免在更新 ref 值时需要使用.value,可以让代码更加精简!请看下面例子:

<template>
  <input type="number" v-model="count"> * 5€
  <h1>{{ total }}</h1>
</template>

<script setup>
  let count = $ref(0)
  let total = $computed(() => count * 5)
</script>

⚠️注意:这还是一个实验性特性,所以请谨慎使用,因为它将来可能会发生变化。该提案还引入了其他新的语法糖,包括$computed()$fromRefs()$raw()

Expose API

Vue 3.2 添加了一个新的 Expose API 来定义组件公开的内容。Expose API 的设想是提供一个像 expose({ ...publicMembers }) 这样的组合式 API,这样组件的作者就可以在 setup() 中使用该 API 来精细设定公开暴露给其他组件的内容。

下例中,该组件只能公开其toggle函数,而不能公开其collapsed变量。

export default defineComponent({
  setup(props, { expose }) {
    const collapsed = ref(true)
    const toggle = () => {
      collapsed.value = !collapsed.value;
    }
    // only expose `toggle` to the parent component
    expose({ toggle })
    return { collapsed, toggle }
  }
})

请注意,所有$实例属性都会自动公开,因此使用Collapse的组件可以访问$props$slots以及其他。<script setup>通过调用defineExpose()函数使用时也可以这样做。

当你在封装组件时,如果嫌ref 中暴露的内容过多,不妨用 Expose API 来约束一下输出吧!

Effect Scope API

Vue 3.2版本引入了新的 Effect scope API,用于创建一个effect Scope对象,该对象可以捕获在其中创建的反应性效果(例如computedwatchers),以便可以将这些效果放在一起并轻松处理它们。它可以更轻松地在组件上下文之外使用 Vue 的响应式 API,同时也在组件之内解锁了多种高级用例。Effect scope 是一种高级 API,主要供库作者使用。

我们知道watch, watchEffect,computed等都是绑定到一个特定的组件实例上的,在组件销毁的时候会被 Vue 自动销毁。这可确保应用程序没有内存泄漏。但是如果你想在组件之外使用这些函数,例如在你正在编写的库中,你需要手动处理它们,请看下例:

import { ref, computed, stop, watchEffect } from 'vue';

const quantity = ref(0);
const price = ref(10);
const total = computed(() => quantity.value * price.value);
const stopWatch = watchEffect(() => console.log(`total changed to ${total.value}`));

let effectsToStop = [];
effectsToStop.push(() => stop(total));
effectsToStop.push(stopWatch);
const stopAll = () => {
  effectsToStop.forEach(f => f())
  effectsToStop = []
};
// calling `stopAll()` disposes of all effects

.prop 和 .attr 修饰符

  • .prop : 被用于强制绑定 DOM 属性 (property)
  • .attr : 被用于强制绑定 DOM 属性 (attribute)

v-bind 默认绑定到 DOM 节点的 attribute 上,使用.prop修饰符后,设置的自定义属性不会在渲染后的 HTML 标签里显示,而.attr修饰符则刚好相反!

.prop修饰符用途:

  • 通过自定义属性存储变量,避免暴露数据
  • 防止污染 HTML 结构
<input id="input" type="foo" value="11" :data.prop="inputData"></input>// 渲染后HTML标签结构<input id="input" type="foo" value="11"></input>

看了它的用途就知道,如果你不想你的属性显示在html标签里面,就用.prop修饰符吧!

另外这两个修饰符有简写的语法:

<a :title.prop="firstTabTooltip" :aria-selected.attr="isFirstTabSelected">First tab</a><!-- 简写 --><a .title="firstTabTooltip" ^aria-selected="isFirstTabSelected">First tab</a>

Web 组件

Vue 3.2 引入了新的 defineCustomElement 方法,可以使用 Vue 组件 API 轻松创建原生自定义元素:

import { defineCustomElement } from 'vue'const MyVueElement = defineCustomElement({  // 常规 Vue 组件选项})// 注册自定义元素。// 注册完成后,此页面上的所有 `<my-vue-element>` 标签// 都将将升级。customElements.define('my-vue-element', MyVueElement)

此 API 允许开发者们创建由 Vue 驱动的 UI 组件库。这些库可以支持任何框架选项,甚至能够在无框架情况下正常使用。

总结

以上诸多特性,最让我感兴趣的是setup script,此语法使单个文件组件更简单!只需要给 script 标签添加一个 setup 属性,那么整个 script 就直接会变成setup函数,所有顶级变量、函数,均会自动暴露给模板使用(无需再一个个 return了),开发效率将大大的提高!

以至于连尤大也在微博上呼吁大家:“如果你能用Vue3却还在用 Options API,现在有了< script setup>没有理由不换 Composition API了”

参考资料

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant