一、vue2中的定义变量和方法的写法
在介绍v3的setup之前,我们先来看看在v2中是如何定义变量和方法的
<template>
<h2>姓名:{{name}}</h2>
<h2>年龄:{{age}}</h2>
<button @click="sayHello">说话</button>
</template>
<script>
export default {
name: 'App',
data() {
return {
name:'张三',
age:'男',
}
},
methods: {
sayHello(){
alert( `你好,我是${this.name},${this.age}岁,很高兴认识你!`)
},
},
}
</script>
如上面的示例,在v2中我们定义变量要写在data方法中,方法要写在methods中
二、setup简单用法介绍
那么我们用v3中的setup同样完成上面案例,如下:
<template>
<h2>姓名:{{name}}</h2>
<h2>年龄:{{age}}</h2>
<button @click="sayHello">说话</button>
</template>
<script>
export default {
name: 'App',
//此处只是测试一下setup,暂时不考虑响应式的问题。
setup(){
//数据
let name = '张三'
let age = 18
//方法
function sayHello(){
alert(`你好,我是${name},${age}岁,很高兴认识你!`)
}
//返回一个对象(常用)
return {
name,
age,
sayHello,
}
}
}
</script>
可以看到,我们只需在setup方法中定义变量和函数,最后通过return将变量和函数暴露出去就可以在template模版中使用了。
就单从写法上而言,是不是感觉v3比v2更简洁呢。v3具有更好的开发体验。
三、setup函数详解
在Vue 3中,setup
函数是一个新引入的特殊函数,用于配置组件的使用。
1. setup函数的执行时机
它是组件实例创建之前第一个被执行的函数,它还在beforeCreate钩子函数之前被调用。
如下示例:
<template>
</template>
<script>
export default {
beforeCreate() {
console.log('beforeCreate');
},
setup() {
console.log('setup函数被调用');
}
}
</script>
2.setup函数具有两个参数:props和context。
我们先定义两个组件,一个父组件,一个子组件
- 子组件TestSetup
<template>
<h2>姓名:{{person.name}}</h2>
<h2>年龄:{{person.age}}</h2>
<button @click="test">测试触发一下Demo组件的Hello事件</button>
</template>
<script>
import {reactive} from 'vue'
export default {
name: 'Demo',
setup(props,context){
console.log('---setup---props',props)
console.log('---setup---',context)
//数据
let person = reactive({
name:'张三',
age:18
})
//方法
function test(){
context.emit('hello',666)
}
//返回一个对象(常用)
return {
person,
test
}
}
}
</script>
- 父组件App.vue
<template>
<test-setup @hello="showHelloMsg" msg="你好啊" hobby="篮球">
<template v-slot:qwe>
<span>插槽qwe</span>
</template>
<template v-slot:asd>
<span>插槽asd</span>
</template>
</test-setup>
</template>
<script>
import TestSetup from './components/TestSetup'
export default {
name: 'App',
components:{TestSetup},
setup(){
function showHelloMsg(value){
alert(`你好啊,你触发了hello事件,我收到的参数是:${value}!`)
}
return {
showHelloMsg
}
}
}
</script>
props
参数:它是一个响应式的对象,包含了组件接收的所有属性。可以通过解构或直接使用props
对象来访问这些属性。
请注意如果你解构了 props 对象,解构出的变量将会丢失响应性。因此我们推荐通过 props.xxx 的形式来使用其中的 props。
如果你确实需要解构 props 对象,或者需要将某个 prop 传到一个外部函数中并保持响应性,那么你可以使用 toRefs() 和 toRef() 这两个工具函数:
举例说明:
在上面的父组件中我们传了msg、和hobby两个属性给子组件,这时我们就可以通过setup的props来接收
props:['msg', 'hobby'],
setup(props) {
const { msg, hobby } = toRefs(props); // 解构属性
console.log(msg.value); // 直接访问单个属性值
}
打印结果如下:
context
参数:它是一个普通的对象,包含与当前组件有关的一些信息和方法。其中最常用的是attrs
、emit
和slots
。
attrs
:一个非响应式的对象,包含了未声明为props
的所有属性。
举例说明:
props:['msg'],
setup(_, context) {
console.log('---setup---',context.attrs.hobby) //访问未声明的属性 相当与Vue2中的$attrs
}
emit
:用于触发父组件中定义的事件,与Vue 2中的$emit
类似。
举例说明:
子组件中context.emit('hello',666)
向父组件触发一个方法hello,并将666作为参数传递过去
<template>
<button @click="test">测试触发一下Demo组件的Hello事件</button>
</template>
<script>
import {reactive} from 'vue'
export default {
emits:['hello'],
setup(props,context){
let person = reactive({
name:'张三',
age:18
})
//方法
function test(){
context.emit('hello',666)
}
//返回一个对象(常用)
return {
person,
test
}
}
}
- 父组件App.vue,通过showHelloMsg方法接收
<template>
<test-setup @hello="showHelloMsg" msg="你好啊" hobby="篮球">
</test-setup>
</template>
<script>
import TestSetup from './components/TestSetup'
export default {
name: 'App',
components:{TestSetup},
setup(){
function showHelloMsg(value){
alert(`你好啊,你触发了hello事件,我收到的参数是:${value}!`)
}
return {
showHelloMsg
}
}
}
</script>
slots
:用于访问插槽内容。在Vue 2中,插槽内容是通过this.$slots
访问的,而在Vue 3中,需要使用context.slots
。
举例说明:
父组件中传递两个插槽
<template>
<test-setup>
<template v-slot:qwe>
<span>插槽qwe</span>
</template>
<template v-slot:asd>
<span>插槽asd</span>
</template>
</test-setup>
</template>
子组件中访问
setup(_, context) {
console.log('---setup---slots',context.slots) //插槽
}
综上所述,setup
函数是Vue 3中用于配置组件使用的特殊函数,它可以接收props
和context
作为参数,并且通过这些参数提供了访问组件属性、上下文相关信息和方法的能力。