一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第7天,点击查看活动详情。
setup的简介
vue2和vue3非常大的区别是在vue2中用的是option-Api而vue3中用的是compoisition-Api,而vue3中的compoisition-Api的入口正是setup函数,今天就来说一说setup函数的用法
setup中的this指向
写在setup中的函数和之前optionsApi中的方法this指向不同,在setup中是没有this指向的,此时的setup指向的是undefined,切记
setup函数中的data
在vue2中我们使用data函数定义数据,在vue3的setup中如何定义呢?
我们可以直接在setup中使用js语法定义一个值,让后把他return出去,就可以在template标签中使用插值语法展示
setup() {
const message = "scc"
return {
message
}
}
我们定义了一个message并且把它return出去,这样在页面就可以拿到message
setup的参数
setup有两个参数,第一个是props,第二个是context
props
props看到这个我们就应该明白他是作用是接收来自父组件的值
但是我们也需要在setup外部使用props接受值,才能使用
我们可以看到,props确实被传进了setup里面
context
context是一个数组,他有三个值,分别是slot,attrs,emit
solt就是父组件传来的插槽,attrs是非props的对象,emit则是传来的方法是一个函数
attrs
我们尝试一下拿到home组件中的id
App组件
<template>
<div>
{{message}}
<home id="home" :message="message"/>
</div>
</template>
在App组件给home组件一个id
home组件中
setup(props,{attrs}) {
console.log(props.message);
console.log(attrs.id);
}
在home组件中打印id
此时的控制台已经输出了id
emit
emit用来触发父组件传递过来方法
在父组件定义一个update方法
父组件
setup() {
const update = ()=>{
console.log("update函数运行");
}
return {
update
}
}
然后在标签上面传递过去,监听change事件
<template>
<div>
<home @change="update"/>
</div>
</template>
子组件
在子组件中触发change事件
<template>
<div>
<button @click="fatherFn">触发父组件change</button>
</div>
</template>
setup(_,{emit}) {
const fatherFn = ()=>{
emit("change")
}
return{
fatherFn
}
}
可以看到按下button出发了父组件的change事件
响应式
我们虽然通过return拿到了定义的数据,但是未经过任何处理,所以肯定是非响应式的
那么如何才能让数据是响应式的呢?
reactive方法
reactive方法接受一个参数,可以是对象或者数组,处理后的数据就是响应式的
<template>
<div>
<div>{{info.num}}</div>
<button @click="update">+1</button>
</div>
</template>
<script>
import { reactive } from 'vue'
export default {
setup() {
//定义一个info对象,采用reactive方法变成响应式
const info = reactive({num:0})
//定义更新数据的方法
const update = ()=>{
info.num++
}
return {
info,
update
}
}
}
我们定义了info对象,使用reactive方法,传入一个数组,并且使用updat方法修改他的值
此时的数据是响应式的
ref方法
ref方法同样可以让数据变成响应式,不同的是它可以直接给单个值,而reactive不可以
<template>
<div>
<div>{{info}}</div>
<button @click="update">+1</button>
</div>
</template>
<script>
import { ref } from 'vue'
export default {
setup() {
const info = ref(0)
const update = ()=>{
info.value++
}
return {
info,
update
}
}
}
我们修改了刚才的代码,把reactive换成了ref,传给ref一个值,但是要记住,想要拿到info的值,需要调用value属性,即info.value,但是在模板中不需要,因为在模板中已经为我们准备好了,会自动解析
readonly只读
readonly可以把数据设置成只读,不允许修改,一般给子组件传值我们都希望他是只读的
readonly接收一个参数,可以是对象,reactive对象,ref对象
对象写法
我们定一个info对象,里面加个name属性,并且添加updat函数尝试修改info的值
<template>
<div>
<div>{{info.name}}</div>
<button @click="update">修改name</button>
</div>
</template>
<script>
import { readonly } from 'vue'
export default {
setup() {
const info = readonly({name:"scc"})
const update = ()=>{
info.name="ooo"
}
return {
info,
update
}
}
}
可以看到,当我们尝试修改info里面的name是,会弹出警告
reactive写法
定义一个reactive的info,在把info传给readonly,readonlyInfo接受readonly返回的数据,定义updat尝试修改readonlyInfo里面的name
setup() {
const info = reactive({name:"scc"})
const readonlyInfo = readonly(info)
const update = ()=>{
readonlyInfo.name="ooo"
}
return {
readonlyInfo,
update
}
}
此时的浏览器同样不允许修改
ref写法
同reactive一样,
<template>
<div>
<div>{{readonlyInfo.name}}</div>
<button @click="update">修改name</button>
</div>
</template>
<script>
import { readonly,ref } from 'vue'
export default {
setup() {
const info = ref({name:"scc"})
const readonlyInfo = readonly(info)
const update = ()=>{
readonlyInfo.value.name="ooo"
}
return {
readonlyInfo,
update
}
}
}
同样,不允许我们修改
结束
compoisitionApi非常多,今天先到这里,明天接着说watch和computed