相比普通script模板优点:
更少的样板内容,更简洁的代码。
能够使用纯 Typescript 声明 props 和抛出事件。
更好的运行时性能 (其模板会被编译成与其同一作用域的渲染函数,没有任何的中间代理)。
更好的 IDE 类型推断性能 (减少语言服务器从代码中抽离类型的工作)
1、使用:
里面的代码会被编译成组件setup()函数的内容,会在每次组件实例被创建的时候执行
与普通的<script>内的setup只在组件被首次引入的时候执行一次不同
<script setup>
console.log('hello script setup')
</script>
2、任何在setup顶层声明的变量、组件、函数、import导入的内容,都能在template中直接使用
<template>
<div>
{{ color }}
{{ ename }}
{{ capitalize('hello') }}
<MyComponent />
<h1 v-my-directive>This is a directive</h1>
</div>
</template>
<script setup lang='ts'>
(1)导入内容
import { capitalize } from './helpers'
(2)导入组件
import MyComponent from './MyComponent.vue'
(3)变量等方式
const color = ref("red");
const ename = "click";
(4)定义props和emits,在typescript下可直接使用ts类型语法,同时使用两种声明方式会导致编译报错
.其他使用格式和选项式一致
const props = defineProps({
foo: String
})
const emit = defineEmits(['change', 'delete'])
(5)向外暴露setup的内容,默认不能通过ref等方式获取到setup中的内容
defineExpose({...})
(6)访问slots和attrs
import { useSlots, useAttrs } from 'vue'
能在普通的组合式API中使用
const slots = useSlots()
const attrs = useAttrs()
(6.5)使用Promise
可直接使用await,结果代码会被编译成async setup()
const post = await fetch(`/api/post/1`).then(r => r.json())
(7)自定义指令
命名必须以v开头,使用时-分隔驼峰
const vMyDirective = {
beforeMount: (el) => {
...
}
}
导入的指令必须符合命名规范才能直接使用
import { myDirective as vMyDirective } from './MyDirective.js'
<script>
(8)和普通<script>一起使用
使用场景
1、无法 <script setup>声明的选项
2、声明命名导出
3、运行副作用或者创建只需要执行一次的对象
<script>
fn() fn只会执行一次
export default {
inheritAttrs: false,
customOptions: {}
和<script setup>一起出现时不支持使用render函数。
}
</script>
<script setup>
...
</script>
(9)不能使用src属性
<script setup src='x/xx.js'> 不能使用src属性,普通script标签可以
(10)响应式语法糖
.不再需要手动调用.value,会在编译时自动添加.value
.无需导入的宏函数
(1)函数语法糖
ref -> $ref
computed -> $computed
shallowRef -> $shallowRef
customRef -> $customRef
toRef -> $toRef
(2)解构赋值语法糖:
const { x, y } = $(useMouse()) 会将解构赋值的内容都变成ref,而不需要手动再调用toRefs
会被编译为:
const __temp = useMouse(),
x = toRef(__temp, 'x'),
y = toRef(__temp, 'y')
console.log(x.value, y.value)
(3)响应式语法糖导致的缺点:
(1)函数传递丢失响应性
let count = $ref(0)
trackChange(count) 无效!因为被编译成了trackChange(count.value)
解决办法:
trackChange($$(count)) $$()表示不会在ref对象后自动追加.value
(2)函数返回值丢失响应性
function useMouse() {
let x = $ref(0)
let y = $ref(0)
fn(...) 监听 mousemove 事件
// 不起效!
return {
x, 因为会被编译成x.value
y
}
}
解决办法:
return $$({
x,
y
})
(4)$$()语法糖
.除了上面的应用外还能将变量转换成ref变量,编译器会高效地通过 toRef 来做转换
const { count } = defineProps<{ count: number }>()
$$(count)
3、递归组件
根据文件名使用,名为FooBar.vue的组件可以在其模板中用<FooBar/>引用它自己
根据文件名推断的优先级低于其他引入方式,如果冲突可使用别名
import { FooBar as FooBarChild } from './components'
4、在typescipt下才能使用的功能
(1)props和emits
const props = defineProps<{
foo: string
bar?: number
}>()
const emit = defineEmits<{
(e: 'change', id: number): void
(e: 'update', value: string): void
}>()
声明默认值
withDefaults辅助函数提供了对默认值的类型检查,并确保返回的props的类型删除了已声明默认值的属性的可选标志
interface Props {
msg?: string
labels?: string[]
}
const props = withDefaults(defineProps<Props>(), {
msg: 'hello',
labels: () => ['one', 'two']
})
vue3.x <script setup>单文件组件
于 2022-02-13 15:04:57 首次发布