vue3 setup语法糖
vue3支持三种写法
- option(选项)API
- composition(组合式)API
<script setup>
composition API的语法糖
option API
- 这种方式也就是我们之前vue2中使用的方式。我们通过一个个的配置,来实现这个组件。
- 然后如果使用ts的话,就增加了一些ts的类型约束。
- defineComponent从vue中导入,只是给组件包装成默认的组件类型。
<script lang="ts">
import { defineComponent } from "vue"
export default defineComponent({
name:'Test',
// props
props : {
msg:{
type:String,
default:''
}
},
// 数据
data(){
return{
count:0
}
},
// 声明周期函数
mounted(){
console.log('mounted')
},
// 自定义方法
methods:{
increment(){
this.count++
}
}
})
</script>
复制代码
这个方法相对于vue2语法,并没有变得很简便,所以我们不提倡用这种方法。
composition API
和选项api的最大不同就是新增了 setup()。我们要处理的逻辑都放到了setup()中
export default defineComponent({
name:'Test',
props : {
msg:{
type:String,
default:''
},
second:{
type:String,
default:'默认'
}
},
setup(){
// 响应式数据
const count = ref(0)
const increment = ()=>{
count.value++
}
// 返回出去 供模板使用
return {
count,
increment
}
}
})
复制代码
setup
在其内部处理数据、和一些逻辑方法。最后需要将这些数据和方法return出去,才可以供模板使用。
如下按钮点击触发increment
方法,让count增加1.
<template>
{{count}}
<el-button @click="increment">增加</el-button>
</template>
<script lang="ts">
import { defineComponent, ref } from "vue"
export default defineComponent({
name:'Test',
setup(){
// 响应式数据
const count = ref(0)
const increment = ()=>{
count.value++
}
// 返回出去 供模板使用
return {
count,
increment
}
}
})
</script>
复制代码
响应式数据
上面的代码中可以看到 ref的使用。那么他的用途就是使 数据成为响应式的数据。
普通数据
我们可以试一试把它改成普通数据,是可以渲染到模板中的。但是点击按钮,页面的渲染是不会改变的。并且,我们分别在increment函数内、和setup作用域中分别打印count。setup内打印
只执行了一次,并且当点击按钮时不会打印。
setup(){
// 响应式数据
let count = 1
const increment = ()=>{
count++
console.log(count,'count函数内打印')
}
console.log(count,'count setup内打印')
// 返回出去 供模板使用
return {
count,
increment
}
}
复制代码

响应式数据
需要从vue中导出ref
import { defineComponent, ref } from "vue"
复制代码
将使用的数据包在ref()中,在对count重新赋值的时候,需要对count的.value
属性赋值。因为经过ref()处理,这个count成了一个对象。我们打印一下可以发现。
let count = ref(0)
const increment = ()=>{
count.value++
console.log(count)
}
复制代码

📢 在模板中不需要.value,在<script>
部分使用count需要.value
缺点
所有方法都要写在setup()中,并且还都需要return出去。当代码中使用的变量和方法较多后。也就不方便了。
setup语法糖
在使用setup语法糖这种写法的时候,我们不需要再去export导出(它默认的把整个<script setup>
标签的内容都进行了export),并且声明props也不可以向上面那么写了。
<script lang="ts" setup>
import { defineComponent, ref } from "vue"
</script>
复制代码
使用响应式数据
一定要注意📢
响应式数据赋值是对其.value
进行。并且声明响应式数据时,是可以使用const关键字的。因为我们是对一个ref对象进行操作的。
<template>
{{count}}
<el-button @click="increment">增加</el-button>
</template>
<script lang="ts" setup>
import { defineComponent, ref } from "vue"
let count = ref(100)
const increment = ()=>{
count.value++
}
</script>
<style>
</style>
复制代码
官方文档
setup语法糖还没有更新到官方文档。我们可以去 GitHub看详细的用法API。

props数据
使用defineProps()
API。这个API其实是不用引入的,但是如果报错提示其没有定义,就从vue中导入一下。
父组件
<template>
<Test msg="from father"/>
</template>
<script lang="ts" setup>
import Test from './Test.vue';
</script>
<style>
</style>
复制代码
子组件
如下使用defineProps()
API,然后我们props接收的值就可以像组合式API中那么写了。这里其实将 defineProps()
赋值给 porps
是为了我们在 <script lang="ts" setup>
内使用props值(这样使用 props.msg
),如果只有模板中使用props值的话,也可以不这样做。
- js 部分使用props,
props.xxx
- template 部分使用porps,
porps.xxx
或xxx
<template>
{{msg}}
<!-- 对应props数据 可以使用props. 也可以不使用 -->
{{props.second}}
{{count}}
<el-button @click="increment">增加</el-button>
</template>
<script lang="ts" setup>
import { defineComponent, defineProps,ref } from "vue"
let count = ref(100)
const props = defineProps({
msg:{
type:String,
default:''
},
second:{
type:String,
default:'second'
}
})
const increment = ()=>{
count.value++
console.log(props.msg)
}
</script>
<style>
</style>
复制代码

defineProps中也可以使用数组 这种情况下就没有默认的 default了。
defineProps(['second','msg'])
复制代码
不要和props内变量同名
注意📢
我们在 <script lang="ts" setup>
内部声明的其他变量,不要和props中的变量同名。
let msg = '不是props'
const props = defineProps({
msg:{
type:String,
default:''
},
second:{
type:String,
default:'second'
}
})
复制代码
如图,页面中的值并不是props中的msg。

子组件传值给父组件
vue3中有类似vue2emit
的API:defineEmits
子组件
- 定义一个变量emit来接收
defineEmits()
方法返回的对象。defineEmits()
,其接收一个数组,数组中写我们要传给父组件的回调函数名(如:increment)。 - 在这个回调函数中调用emit
emit('increment',param)
第一个参数是回调函数名,第二个参数是函数的参数,如果没有就需要写
<template>
{{msg}}
{{second}}
{{count}}
<el-button @click="increment('test')">增加</el-button>
</template>
<script lang="ts" setup>
import { defineEmits, defineProps,ref } from "vue"
let count = ref(100)
const props = defineProps({
msg:{
type:String,
default:''
},
second:{
type:String,
default:'second'
}
})
// 接收返回值
const emit = defineEmits(['increment'])
const increment = (param:string)=>{
count.value++
emit('increment',param)
}
</script>
<style>
</style>
复制代码
父组件
- 注意这个回调方法要用 @
- 还要声明相应的方法
increment
<template>
<Test msg="from father" @increment="increment"/>
</template>
<script lang="ts" setup>
import { getLoginInfo } from '@/api/common';
import Test from './Test.vue';
import { onMounted } from 'vue';
const increment = (param:string)=>{
console.log(param)
}
</script>
<style>
</style>