Vue3语法糖setup(一)

425 阅读4分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 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.png 我们可以看到,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

logId.png 此时的控制台已经输出了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
}
}

change事件.gif 可以看到按下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方法修改他的值

更新数据.gif 此时的数据是响应式的

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,但是在模板中不需要,因为在模板中已经为我们准备好了,会自动解析

ref.gif

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
        }
    }
}

changeName.gif 可以看到,当我们尝试修改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
    }
}

readonlyReactive.gif 此时的浏览器同样不允许修改

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
        }
    }
}

readonlyRef.gif 同样,不允许我们修改

结束

compoisitionApi非常多,今天先到这里,明天接着说watch和computed