vue3的<script setup>提案处于实验阶段已经几个月了,当我们用vite的vue模板时终端会提示我们这仍是一个实验性提案,并且建议我们如果使用这个写法要锁vue版本以避免breakage。所以之前我只是对这个提案做了个了解,并没有在工作中使用这个写法。终于我们在2021年6月29日上午迎来了他的Finalization,下面简单梳理下这个定稿的内容。
以下内容会在3.1.3版本中被实装,但是要到3.2版本才会正式移除这个提案的“实验性”状态,同时下面提及的将被废弃API也要到3.2版本才会被移除,再此之前新老API将共存一段时间。
废弃useContextAPI
之前的用法是这样的:
1 | import { useContext} from 'vue' |
3.2版本后这个API就将被移除,被拆分成几个新的API来取代
新增 useAttrsAPI
attrs是父组件传递给子组件的属性中除了props、class以及style外的属性:
1 | // 父组件 |
比如上面的代码,父组件向子组件传递了若干属性,我们假设child组件定义了一个msgprop,那么子组件接收到的attrs就是{a: "1", b: "2"}。
老的用法:
1 | import { useContext} from 'vue' |
新的用法:
1 | import { useAttrs } from 'vue' |
新增 useSlotsAPI
useSlots一般是用JSX才会用到,做个了解,下面提供新的写法,老的写法就是把useSlots换成const slots = useContext()就行了:
1 | // 父组件 |
1 | // 子组件 |
新增 defineExposeAPI
当使用<script setup>时,可以把<template>看成是setup作用域内的一个function,这样setup就相当于一个闭包,除了内部的<template>谁都访问不到其作用域内的数据。就像下面的代码这样:
1 | function setup() { |
所以,传统setup写法里我们可以在父组件中通过子组件的ref实例来访问子组件的数据和方法(childRef.value.someFn()),到了<script setup>里这一套就行不通了,需要显示地向外暴露你想暴露的内容。
用老的useContextAPI是这么玩得:
1 | // 子组件 |
用新的defineExposeAPI:
1 | import { defineExpose } from 'vue' |
defineEmit -> defineEmits
defineEmitdefineEmitAPI被更名为defineEmits了,因为不管是选项emits,props还是APIdefineProps都是复数,之前的defineEmit就显得有点扎眼了,统一改成复数了,用法不变。
1 | import { defineEmits } from 'vue' |
新增 withDefaultsAPI
当我们在vue中使用TS时,定义props类型有两种方法:
- 是用原生js的构造函数
String, Boolean, Number, Array等:
1 | import { defineProps } from 'vue' |
- 用TS类型来定义:
1 | import { defineProps } from 'vue' |
但是,使用第二种方式时,是无法定义props默认值的。使用新增的 withDefaultsAPI就能实现props默认值定义,它接收两个参数,第一个是defineProps(),第二个是默认值:
1 | import { defineProps, withDefaults } from 'vue' |
恢复指令的v前缀
现在要使用v-my-dir这样的指令,在定义指令变量是必须使用vMyDir,也就是加上v前缀。
1 | <script setup> |
顶级await支持
现在可以直接在<script setup>块的顶级写await而不用放在async函数内了,会被自动编译成async setup()。
移除<template>上的inherit-attrs属性
如何定义诸如name这样的选项?
这一条和上一条一起回答,用一个平级于<script setup>的独立的<script>块来定义:
1 | <script> |
See Declaring Additional Options and Automatic Name Inference.