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