Open ljianshu opened 3 years ago
8.10号凌晨,尤雨溪在微博平台官宣 Vue 3.2 版本正式发布:
此版本包含一系列重要的新功能与性能改进,但并不涉及任何重大变更。本文主要介绍一些相对重要 Vue3.2新特性,如需了解更多请查阅官方文档!
关于单文件组件(SFC,即.vue 文件)的两项功能已经由实验状态正式毕业,现提供稳定版本:
<script setup>
<style> v-bind
<style>
在<script setup>中,我们不必声明export default和setup方法,这种写法会自动将所有顶级变量、函数,均会自动暴露给模板(template)使用。我们先来通过一个例子,对比script setup前后写法的不同,直观感受下setup带给我们的便利:
export default
setup
script 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>的使用还有些细节和注意事项,我将会在下一篇文章详细介绍。
挺有趣的一个新特性,通过这个指令,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>
点击按钮更改color 或者 fontSize的数值,可以看到页面样式也会响应式变化。其原理就是自定义属性将通过内联样式应用于组件的根元素,并在数值更改时进行响应更新。
color
fontSize
3.2 版本为 Vue 的响应式系统带来了一系列重大性能改进,具体包括:
新版本还提供新的 v-memo 指令,可实现对部分模板树的记忆功能。当v-memo 命中时,不仅允许 Vue 跳过虚拟 DOM 差异、甚至可以完全跳过新 VNode 的创建步骤。虽然这个指令使用频率不高,但它提供了一个逃生舱来在某些情况下(例如处理大型 v-for 列表)获取最大性能。
v-memo
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.name或selectedUserId发生变化,div则将更新。
user.name
selectedUserId
div
$ref()避免在更新 ref 值时需要使用.value,可以让代码更加精简!请看下面例子:
$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()。
$computed()
$fromRefs()
$raw()
Vue 3.2 添加了一个新的 Expose API 来定义组件公开的内容。Expose API 的设想是提供一个像 expose({ ...publicMembers }) 这样的组合式 API,这样组件的作者就可以在 setup() 中使用该 API 来精细设定公开暴露给其他组件的内容。
Expose API
expose({ ...publicMembers })
setup()
下例中,该组件只能公开其toggle函数,而不能公开其collapsed变量。
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()函数使用时也可以这样做。
$
Collapse
$props
$slots
defineExpose()
当你在封装组件时,如果嫌ref 中暴露的内容过多,不妨用 Expose API 来约束一下输出吧!
ref
Vue 3.2版本引入了新的 Effect scope API,用于创建一个effect Scope对象,该对象可以捕获在其中创建的反应性效果(例如computed 或 watchers),以便可以将这些效果放在一起并轻松处理它们。它可以更轻松地在组件上下文之外使用 Vue 的响应式 API,同时也在组件之内解锁了多种高级用例。Effect scope 是一种高级 API,主要供库作者使用。
Effect scope API
effect Scope
computed
watchers
Effect scope
我们知道watch, watchEffect,computed等都是绑定到一个特定的组件实例上的,在组件销毁的时候会被 Vue 自动销毁。这可确保应用程序没有内存泄漏。但是如果你想在组件之外使用这些函数,例如在你正在编写的库中,你需要手动处理它们,请看下例:
watch
watchEffect
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
v-bind 默认绑定到 DOM 节点的 attribute 上,使用.prop修饰符后,设置的自定义属性不会在渲染后的 HTML 标签里显示,而.attr修饰符则刚好相反!
.prop修饰符用途:
<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>
Vue 3.2 引入了新的 defineCustomElement 方法,可以使用 Vue 组件 API 轻松创建原生自定义元素:
defineCustomElement
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了),开发效率将大大的提高!
setup script
script
以至于连尤大也在微博上呼吁大家:“如果你能用Vue3却还在用 Options API,现在有了< script setup>没有理由不换 Composition API了”
前言
8.10号凌晨,尤雨溪在微博平台官宣 Vue 3.2 版本正式发布:
此版本包含一系列重要的新功能与性能改进,但并不涉及任何重大变更。本文主要介绍一些相对重要 Vue3.2新特性,如需了解更多请查阅官方文档!
新的 SFC 功能
关于单文件组件(SFC,即.vue 文件)的两项功能已经由实验状态正式毕业,现提供稳定版本:
<script setup>
是一种编译时语法糖,能够极大改善在 SFC 中使用 Composition API 时的开发者体验。<style> v-bind
用于在 SFC<style>
标签中启用组件状态驱动的动态 CSS 值。1、
<script setup>
在
<script setup>
中,我们不必声明export default
和setup
方法,这种写法会自动将所有顶级变量、函数,均会自动暴露给模板(template)使用。我们先来通过一个例子,对比script setup
前后写法的不同,直观感受下setup
带给我们的便利:从上面的例子来看,
<script setup>
语法省去了组件Card的注册步骤,以及return变量message的语句,使得代码更为精简。关于<script setup>
的使用还有些细节和注意事项,我将会在下一篇文章详细介绍。2、
<style> v-bind
挺有趣的一个新特性,通过这个指令,Vue SFC 的 CSS 灵活性将大大提高。该指令适用于
<script setup>
, 并支持 JavaScript 表达式(必须用引号括起来)。点击按钮更改
color
或者fontSize
的数值,可以看到页面样式也会响应式变化。其原理就是自定义属性将通过内联样式应用于组件的根元素,并在数值更改时进行响应更新。v-memo
3.2 版本为 Vue 的响应式系统带来了一系列重大性能改进,具体包括:
新版本还提供新的
v-memo
指令,可实现对部分模板树的记忆功能。当v-memo
命中时,不仅允许 Vue 跳过虚拟 DOM 差异、甚至可以完全跳过新 VNode 的创建步骤。虽然这个指令使用频率不高,但它提供了一个逃生舱来在某些情况下(例如处理大型v-for
列表)获取最大性能。这个例子使用
v-memo
,不会重新创建虚拟元素,并且会重新使用前一个元素,除非v-memo
(此处为用户名)的条件发生变化。这可能看起来是一个很小的改进,但如果您渲染大量元素,它实际上是性能的巨大改进。其实
v-memo
可以接受一组条件,请看下面的例子:此时如果
user.name
或selectedUserId
发生变化,div
则将更新。新 ref 语法糖(实验性)
$ref()
避免在更新 ref 值时需要使用.value
,可以让代码更加精简!请看下面例子:⚠️注意:这还是一个实验性特性,所以请谨慎使用,因为它将来可能会发生变化。该提案还引入了其他新的语法糖,包括
$computed()
、$fromRefs()
和$raw()
。Expose API
Vue 3.2 添加了一个新的
Expose API
来定义组件公开的内容。Expose API
的设想是提供一个像expose({ ...publicMembers })
这样的组合式 API,这样组件的作者就可以在setup()
中使用该 API 来精细设定公开暴露给其他组件的内容。下例中,该组件只能公开其
toggle
函数,而不能公开其collapsed
变量。请注意,所有
$
实例属性都会自动公开,因此使用Collapse
的组件可以访问$props
,$slots
以及其他。<script setup>
通过调用defineExpose()
函数使用时也可以这样做。当你在封装组件时,如果嫌
ref
中暴露的内容过多,不妨用Expose API
来约束一下输出吧!Effect Scope API
Vue 3.2版本引入了新的
Effect scope API
,用于创建一个effect Scope
对象,该对象可以捕获在其中创建的反应性效果(例如computed
或watchers
),以便可以将这些效果放在一起并轻松处理它们。它可以更轻松地在组件上下文之外使用 Vue 的响应式 API,同时也在组件之内解锁了多种高级用例。Effect scope
是一种高级 API,主要供库作者使用。我们知道
watch
,watchEffect
,computed
等都是绑定到一个特定的组件实例上的,在组件销毁的时候会被 Vue 自动销毁。这可确保应用程序没有内存泄漏。但是如果你想在组件之外使用这些函数,例如在你正在编写的库中,你需要手动处理它们,请看下例:.prop 和 .attr 修饰符
.prop
: 被用于强制绑定 DOM 属性 (property).attr
: 被用于强制绑定 DOM 属性 (attribute)v-bind 默认绑定到 DOM 节点的 attribute 上,使用
.prop
修饰符后,设置的自定义属性不会在渲染后的 HTML 标签里显示,而.attr
修饰符则刚好相反!.prop
修饰符用途:看了它的用途就知道,如果你不想你的属性显示在html标签里面,就用
.prop
修饰符吧!另外这两个修饰符有简写的语法:
Web 组件
Vue 3.2 引入了新的
defineCustomElement
方法,可以使用 Vue 组件 API 轻松创建原生自定义元素:此 API 允许开发者们创建由 Vue 驱动的 UI 组件库。这些库可以支持任何框架选项,甚至能够在无框架情况下正常使用。
总结
以上诸多特性,最让我感兴趣的是
setup script
,此语法使单个文件组件更简单!只需要给script
标签添加一个setup
属性,那么整个script
就直接会变成setup
函数,所有顶级变量、函数,均会自动暴露给模板使用(无需再一个个 return了),开发效率将大大的提高!以至于连尤大也在微博上呼吁大家:“如果你能用Vue3却还在用 Options API,现在有了< script setup>没有理由不换 Composition API了”
参考资料