尤大在 Vue 3.2 发布的时候就给出了项目最佳实践的解决方案:
<script setup>
+TS =
+Volar
如此可见<setup script>
的地位举足轻重,是我们写Vue3绕不过的话题;
在Vue3当中,引入了Composition API
,我们可以通过编写setup
函数来作为API的入口来使用,它也是Vue3一大特性函数,对于之前Options API
分散的写法,我们可以把控制代码统统放在setup
函数当中,实现数据的展示和功能的实现
而对于<setup script>
,简单来讲,它是vue3新出的一个语法糖,里面的代码会被编译成组件 setup()
函数的内容,会极大地方便日常代码的书写。
官方文档指路:v3.cn.vuejs.org/api/sfc-scr…
它的优势说明:
- 更少的样板内容,更简洁的代码。
- 能够使用纯 TypeScript 声明 props 和抛出事件。
- 更好的运行时性能 (其模板会被编译成与其同一作用域的渲染函数,没有任何的中间代理)。
- 更好的 IDE 类型推断性能 (减少语言服务器从代码中抽离类型的工作)
具体代码编写姿势:
1. 自动注册子组件
直接import所需要的组件之后就可以直接使用,会自动完成组件的注册;
在传统script
代码中,子组件在import
之后需要通过components
进行注册才能使用,而在setup
语法糖当中会帮助我们自动完成组件的注册;
传统script
写法:
<template>
<div>
<MyComponent />
</div>
</template>
<script>
import { defineComponent, ref } from 'vue';
// 组件
import MyComponent from './MyComponent.vue'
export default defineComponent({
components: {
MyComponent
},
setup() {}
});
</script>
setup script
写法:
<script setup>
import MyComponent from './MyComponent.vue'
</script>
<template>
<MyComponent />
</template>
2. 简化返回
在setup
函数中,需要返回定义的变量和方法名才能在模板当中使用,而语法糖当中顶层定义的属性和方法不需要再手动返回
传统script
写法:
<template>
<div>
<h2>{{msg}}</h2>
</div>
</template>
<script>
import { defineComponent, ref } from 'vue';
export default defineComponent({
setup() {
const msg = ref('Hello!')
const showMsg = () => {
console.log(msg.value)
}
return {
msg,
showMsg
}
}
});
</script>
setup script
写法
<script setup>
// 变量
const msg = ref('Hello!')
// 函数
const showMsg = () => {
console.log(msg.value)
}
</script>
<template>
<div @click="showMsg">{{msg}}</div>
</template>
3. defineProps
、defineEmit
接受props
、emit
传统script
代码:
<template>
我是子组件{{title}}
<div @click="backData"></div>
</template>
<script >
import { defineComponent } from 'vue'
export default defineComponent({
//或者props:['title'],
props:{
title:{
type:String,
default:''
}
},
emits: ["getData"],
setup (props,{emit}) {
const backData = () => {
emit('getData', 123) //getData为父组件中定义的接收函数
}
return {
backData
}
}
})
</script>
setup script
写法:
<template>
<div>
<h2 >父组件</h2>
<Child msg="hello" @child-click="childCtx" />
</div>
</template>
<script setup>
import Child from './Child.vue'; //point 1:自动注册子组件
const childCtx = (ctx) => { //point 2:属性不需返回
console.log(ctx);
}
</script>
//Child.vue
<template>
<span @click="handleClick">子组件 -- msg: {{ props.msg }}</span>
</template>
<script setup lang=ts>
import { defineProps, defineEmit } from 'vue'
//typescript中props与emit写法
const props = defineProps<{
msg: string
}>()
const emit = defineEmits<{
(e: 'child-click', value: string): void
}>()
//——end
const handleClick = () => {
emit('child-click', 'xxx')
}
</script>
TS
中带有默认值的props
写法:
interface Props {
msg?: string
labels?: string[]
}
const props = withDefaults(defineProps<Props>(), {
msg: 'hello',
labels: () => ['one', 'two']
})
4. defineExpose API
在传统的写法中,可以在父组件中,通过ref
实例的方式去访问子组件的内容,但在script setup
中,该方法就不能用了,在setup
,除了内部的template
模板,谁都不能访问内部的数据和方法。这时候可以将属性和方法通过defineExpose
暴露出去
<script setup>
import { ref } from 'vue'
const a = 1
const b = ref(2)
defineExpose({
a,
b
})
</script>
5. components :is
动态组件
当我们不确定某个位置具体要用那个组件时,通常会用到<components/>
标签,并结合:is
属性对组件名进行动态绑定,当多个组件切换时非常方便;Vue3
当中的setup script
同样支持这种写法,只不过,我们需要注意以下的用法差异:
使用语法糖时,:is
的值改为组件,字符串将不生效,通常可以通过一个变量来进行控制
传统script
代码写法(和Vue2基本一致):
<template>
<component :is="currentComp"></component>
<el-button @click="compChange">切换组件</el-button>
</template>
<script>
import { ref } from 'vue'
import Child1 from './Child1.vue'
import Child2 from './Child2.vue'
export default {
components: {
Child1,
Child2
},
setup() {
let currentComp = ref('Child1')
// 切换组件
const compChange = () => {
if(currentComp.value == 'Child1') {
currentComp.value = 'Child2'
}else {
currentComp.value = 'Child1'
}
}
return {
currentComp,
compChange
}
}
}
</script>
setup script
写法:
<template>
<-- 注意这里的Chlid1、Chlid2为组件类型 -->
<component :is="flag ? Child1 : Child2"></component>
<el-button @click="flag = !flag">切换组件</el-button>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import Child1 from './Child1.vue'
import Child2 from './Child2.vue'
const flag = ref(true)
</script>
6. 自定义指令
指令和组件一样,导入会自动进行注册,在符合命名规范的前提下可以直接在模板当中使用(必须以 vNameOfDirective
的形式来命名本地自定义指令)
<script setup>
const vMyDirective = { //定义指令
beforeMount: (el) => {
// 在元素上做些操作
}
}
</script>
<template>
<h1 v-my-directive>This is a Heading</h1> //在当前文件中直接使用
</template>
//在另一个文件当中,通过导入使用
<script setup>
// 也能够通过重命名来使其符合命名规范
import { myDirective as vMyDirective } from './MyDirective.js'
</script>
7. 兼容使用
在使用<script setup>
的同时,是可以和普通的<script>
标签一起使用的,只是两者的执行机制是不同的,普通<script>
, 只会执行一次,而<script setup>
中的代码,相当于写在了setup
函数当中,在 setup()
作用域中执行,不止一次
尾
当然,对于<setup script>
不仅仅只是这六点特性,本文只是列举的日常开发当中比较常见的一些情景,如果你仅仅只是需要立马上手Vue3,了解完这些就可以去写代码啦~
对于其他的内容官网上面都解释的非常清楚,非常建议大家养成看官网的好习惯👀👀👀