vue3.2正式版已经发布,script setup语法已经由实验性质改为了正式语法,可以放心大胆的在项目中用了。
官方文档:https://v3.cn.vuejs.org/api/sfc-script-setup.html#basic-syntax
相比于常规的composition api语法,script setup语法更加简练方便,不过它本身只是个语法糖,最终还是转换为composition api语法运行。官方文档纯英文且不够详细,下面分享一下个人整理的语法使用方式。
<template>
<Foo :count="count" @click="inc" />
</template>
<script lang="ts" setup>
import { ref } from 'vue'
import Foo from './Foo.vue'
const count = ref(0)
const inc = () => {
count.value++
}
</script>
<template>
<div @click="onClick">{{foo}}</div>
</template>
<script lang="ts" setup>
import { defineProps, defineEmits } from 'vue'
// 定义props属性
const props = defineProps({
foo: {
type: String,
default: '',
}
})
// 定义emit事件
const emit = defineEmits({
'onSubmit': null,
})
function onClick () {
emit('onSubmit', { val: props.foo })
}
</script>
<template>
<div v-click-outside />
</template>
<script lang="ts" setup>
import { directive as vClickOutside } from 'v-click-outside'
</script>
这个defineExpose是干什么的呢,因为script setup默认是不对外界暴露组件实例的,所以在其他组件中通过诸如$refs
和$parent
都默认无法获取当前组件实例,但是通过defineExpose暴露的可以获取。(这个设计非常好,对于防止代码耦合很有用)
Child.vue
:<script lang="ts" setup>
import { ref } from 'vue'
const aaa = 1
const bbb = ref(2)
const ccc = ref(3)
defineExpose({
aaa,
bbb
})
</script>
<template>
<Child ref="refChild" />
<div @click="onClick">123</div>
</template>
<script lang="ts" setup>
import Child from './Child.vue'
const refChild = ref<any>(null) // 定义同名ref,和template模板中Child的ref属性同名,即可代表Child组件实例
function onClick () {
console.log(refChild.value) // { aaa: 1, bbb: 2 }
}
</script>
<script lang="ts" setup>
import { useSlots, useAttrs } from 'vue'
const slots = useSlots()
const attrs = useAttrs()
</script>
$slots
和$attrs
的效果。$slots
主要用于获取作用域插槽,典型应用场景:base基础组件的封装;$attrs
主要用于获取父组件绑定属性,典型应用场景:第三方组件的二次封装。具体使用方式比较复杂,这里不再赘述。有些setup()之外的配置项在script setup中不适用,可以结合普通script一起使用。
<script lang="ts">
// 普通<script>, 只会执行一次
runSideEffectOnce()
// 声明一些额外的配置选项
export default {
name: 'CompName',
inheritAttrs: false,
customOptions: {}
}
</script>
<script lang="ts" setup>
// script setup语法区域
</script>
在script setup下的顶层作用域下可以直接使用await,
<script setup>
const post = await fetch(`/api/post/1`).then(r => r.json())
</script>
<suspense>
使用,目前<suspense>
还在试验阶段,未来应该会成为vue正式功能,官方文档:https://v3.cn.vuejs.org/guide/migration/suspense.html#%E4%BB%8B%E7%BB%8Dscript setup语法推荐使用Volar扩展插件配合使用,效果和Vetur类似,但是对script setup语法的兼容性更好。
需要注意Volar和Vetur两个是互斥的,使用Volar时要记得禁用Vetur。