2.1 setup概述
setup是Vue3中一个新的配置项,值是一个函数,它是Composition API表演的舞台,组件中所用到的:数据、方法、计算属性、监视......等等,均配置在setup中。
2.1.1 setup写数据
在Vue2中,数据是写在data里,在setup里直接使用变量定义,然后return返回,模板即可读取该变量。
Vue2:
<template>
<div class="person">
<h2>姓名:{{name}}</h2>
<h2>年龄:{{age}}</h2>
</div>
</template>
<script>
export default {
name:'Person',
data() {
return {
name: '张三'
age: 18
tel: '13888888888'
}
}
}
</script>
Vue3:
<template>
<div class="person">
<h2>姓名:{{name}}</h2>
<h2>年龄:{{age}}</h2>
</div>
</template>
<script lang="ts">
export default {
name:'Person',
setup(){
let name = '张三'
let age = 18
let tel = '13888888888'
return {name,age,tel}
}
}
</script>
2.1.2 setup写方法
在Vue2中,方法是写在methods里,在setup里可以直接写function,同样需要return返回,模板就能识别该方法。
Vue2:
<template>
<div class="person">
<h2>姓名:{{name}}</h2>
<h2>年龄:{{age}}</h2>
<button @click="changeName">修改名字</button>
<button @click="changeAge">修改年龄</button>
<button @click="showTel">查看联系方式</button>
</div>
</template>
<script>
export default {
name:'Person',
data(){
return {
name:'张三',
age:18,
tel:'13888888888'
}
},
methods:{
// 修改姓名
changeName(){
this.name = 'zhang-san'
},
// 修改年龄
changeAge(){
this.age += 1
},
// 展示联系方式
showTel(){
alert(this.tel)
}
}
}
</script>
Vue3:
<template>
<div class="person">
<h2>姓名:{{name}}</h2>
<h2>年龄:{{age}}</h2>
<button @click="changeName">修改名字</button>
<button @click="changeAge">修改年龄</button>
<button @click="showTel">查看联系方式</button>
</div>
</template>
<script lang="ts">
export default {
name:'Person',
setup(){
let name = '张三'
let age = 18
let tel = '13888888888'
// 方法
function changeName() {
name = 'zhang-san'
}
function changeAge() {
age += 1
}
function showTel() {
alert(tel)
}
// 将数据、方法交出去,模板中才可以使用
return {name,age,tel,changeName,changeAge,showTel}
}
}
</script>
注意1:此时的数据并不是响应式的,也就是说变量的值改变了,并没有同步刷新视图。
关于响应式的问题,可以参考# Vue3+vite+Ts+pinia—第三章 ref-reactive-toRefs-toRef
注意2:在setup里,是没有this作用域的,也就是说在setup里不能用this。
<script lang="ts">
export default {
name:'Person',
setup(){
console.log(this);
......
}
}
</script>
2.1.3 setup执行时机
在Vue2中,在所有生命周期中最早执行的是beforeCreate,而setup执行时机比beforeCreat更快。
export default {
name:'Person',
beforeCreate(){
console.log('beforeCreate')
},
setup(){
console.log('setup')
}
}
2.1.4 代码示例
2.2 setup的返回值
一般来说,setup返回的是一个对象,里面包含着定义的变量和方法,给模板使用。但它也可以返回一个函数,它可以直接指定渲染的内容,覆盖掉<template>
模板的内容,也就是说,你可以在函数里写页面。
<template>
<div class="person">
<h2>姓名:{{name}}</h2>
<h2>年龄:{{age}}</h2>
<button @click="changeName">修改名字</button>
<button @click="changeAge">修改年龄</button>
<button @click="showTel">查看联系方式</button>
</div>
</template>
<script lang="ts">
export default {
name:'Person',
setup(){
......
return () => '哈哈'
}
}
</script>
2.3 setup与OptionsAPI
学完setup会产生以下几个问题:
1、setup与data、methods有什么关系呢?
2、setup与data、methods这些传统的配置项可否同时写,以谁为主?
3、setup可否读取data的变量?又或者data、methods可否读取setup变量?
实际上按正常开发Vue3而言,是不应该出现这些问题的,因为用了Vue3就不应该再用data、methods,但由于Vue3又是支持Vue2的语法,这样就难免在开发过程中,有开发者既写Vue2也写Vue3语法,混着来写。因此这些概念就必须得弄明白。
2.3.1 setup与data、methods并存
虽然在setup定义了数据和方法,但如果此时也写了data和methods,Vue3一样能识别。
<template>
<div class="person">
<h2>姓名:{{name}}</h2>
<h2>年龄:{{age}}</h2>
<button @click="changeName">修改名字</button>
<button @click="changeAge">修改年龄</button>
<button @click="showTel">查看联系方式</button>
<hr>
<h2>测试1:{{a}}</h2>
<button @click="b">测试</button>
</div>
</template>
<script lang="ts">
export default {
name:'Person',
data(){
return {
a:100
}
},
methods:{
b(){
console.log('b')
}
},
setup(){
let name = '张三'
let age = 18
let tel = '13888888888'
// 方法
function changeName() {
name = 'zhang-san'
}
function changeAge() {
age += 1
}
function showTel() {
alert(tel)
}
return {name,age,tel,changeName,changeAge,showTel}
}
}
</script>
说明无论是数据还是方法,写在setup或者data、methods都是可以的,只是不推荐在Vue3再使用旧语法而已。
2.3.2 setup与data的关系
setup与data之间能否相互通信?答案是setup不能读取data变量,但data可以读取setup变量。在Vue3中,setup是最快执行的函数,因此在data定义之前,setup变量已经存在。反过来setup是不能读data变量的,在setup执行的时候,data变量还没开始定义。
<template>
<div class="person">
......
<h2>测试1:{{a}}</h2>
<h2>测试2:{{c}}</h2>
<button @click="b">测试</button>
</div>
</template>
<script lang="ts">
export default {
name:'Person',
data(){
return {
a:100,
c:this.name
}
},
methods:{
b(){
console.log('b')
}
},
setup(){
let name = '张三'
let age = 18
let tel = '13888888888'
......
}
}
</script>
2.3.3 示例代码
2.4 setup语法糖
因为使用setup函数,它是必须要return返回的,这样模板才可以读取。但是随着变量和方法越来越多,那么要return的东西就越多,而且还会存在忘记return的情况。
2.4.1 <script>标签添加setup
在<script>标签添加setup的作用是,它里面的内容就相当于setup(){}函数一样,而且还帮我们return返回,非常方便,这里举一个最简单的例子对比一下:
1、setup函数写法
<script lang="ts">
export default {
name:'Person',
setup(){
let a = 666
return {a}
}
}
</script>
2、<script>加setup
<script lang="ts">
export default {
name:'Person'
}
</script>
<script setup>
let a = 666
</script>
此时它会报一个错误,说<script>与<script setup>必须是相同的语言类型,因为现在存在两个<script>,一个加了lang="ts",而setup的<script>没加,这里只需在setup的<script>也加上lang="ts"即可。
<script lang="ts">
export default {
name:'Person'
}
</script>
<script lang="ts" setup>
let a = 666
</script>
2.4.2 两个<script>合二为一
现在还存在一个问题,就是现在虽然把setup抽离到另一个<script>,但之前的<script>用来配置组件名的,这个倒不能随便合并在一起,因为<script>配置了setup就意味着它里面的是setup函数的内容,不能在里面写export default这些东西。
删掉没有setup的<script>标签是没问题的,程序仍然能正常运行:
<template>
<div class="person">
<h2>姓名:{{name}}</h2>
<h2>年龄:{{age}}</h2>
<h2>地址:{{address}}</h2>
<button @click="changeName">修改名字</button>
<button @click="changeAge">修改年龄</button>
<button @click="showTel">查看联系方式</button>
</div>
</template>
<script lang="ts" setup>
let name = '张三'
let age = 18
let tel = '13888888888'
let address = '北京昌平区宏福苑·宏福科技园'
// 方法
function changeName() {
name = 'zhang-san'
}
function changeAge() {
age += 1
}
function showTel() {
alert(tel)
}
</script>
但如果此时想改变组件名就麻烦了,在Vue中组件名是读取你配置的name属性,现在删掉了就等于没有配置name属性,那就读取文件名作为组件名。
此时如果想给组件改名,除非是修改文件名,显然这个是不能随便改的。除此之外,我们还可以借助vite中的插件简化:
1、npm i vite-plugin-vue-setup-extend -D
2、vite.config.ts
import { defineConfig } from 'vite'
import VueSetupExtend from 'vite-plugin-vue-setup-extend'
export default defineConfig({
plugins: [ VueSetupExtend() ]
})
3、在<scrpit>标签添加name属性
<script setup lang="ts" name="Person234">
当然改组件名的情况并不是很多,但是如果一些公司规范是所有组件的文件名都叫index.vue,在外面包裹一个组件业务名,如下图所示,此时修改组件名就比较有用。