看一眼,Vue3 script-setup语法糖下组件通信就学会了(附源码)

4,704 阅读2分钟

小知识,大挑战!本文正在参与「程序员必备小知识」创作活动

本文已参与「掘力星计划」,赢取创作大礼包,挑战创作激励金

前言:最近在做一个项目技术栈是选用Vite + Vue3 + typescript, 发现script-setup这语法糖有点意识,本文主要介绍如何快速在setup语法糖下实现父子组件间的通信

关于script-setup语法糖

该语法糖其实就是在script标签里加setup,例如

<script setup>
    console.log('1')
</script>

setup代码里的执行时机

<script setup>是Vue3新增的语法糖,setup里面的代码会在组件实例被创建时执行,和普通的script标签只在首次引入的时候不一样,实际是围绕着Vue2的created()beforeCreate()这两个生命周期钩子里运行的,因此之前在created()beforeCreate()里写的代码,可以直接在setup里面写。

// Vue 2 index.vue
<template>
    <div>hello Vue {{ version }}</div>
</template>
<script>
export default {
    data() {
        version: 2
    },
    // init events & lifecircle
    beforeCreate: function () {
        // do something beforeCreated
    },
    // init injection & reactivity
    created: function () {
        // do something created
    },
}
</script>

在Vue3的<script setup>语法糖里可以直接精简成下面的写法:

// Vue 3 index.vue
<template>
    <div>hello {{ version }}</div>
</template>
<script setup>
    import { ref } from 'vue'
    const version = ref('Vue 3')
    // do something beforeCreated
    // do something created
</script>

setup里的顶层绑定会暴露给组件

  • 使用setup函数,需要主动return里面的方法和变量给模版
<template>
    <div>hello {{ name }} {{ version }}, {{ desc }}</div>
    <ChildrenComponent />
</template>
<script>
import { ref } from 'vue'
import ChildrenComponent from './components/ChildrenComponent.vue'
export default {
    data() {
        name: 'Vue'
        version: 3
    },
    components: {
        ChildrenComponent
    },
    setup() {
        const desc = ref('觉得内容不错,可以给个赞我吗 ≧▽≦ ')
        // 暴露给模版
        return {
            desc
        }
    }
}
</script>
  • 使用 <script setup> 语法糖实现,可以直接把setup里定义的变量,方法以及import的内容直接暴露,例如import进来的ChildrenComponent组件,不用再通过components再传入
```javascript
<template>
    <div>hello {{ name }} {{ version }}, {{ desc }}</div>
    <ChildrenComponent />
</template>
<script setup>
import { ref } from 'vue'
import ChildrenComponent from './components/ChildrenComponent.vue'
const desc = ref('觉得内容不错,可以给个赞我吗 ≧▽≦ ')
const name = ref('Vue')
const version = ref(3)
</script>

setup里的响应式状态需要用ref显示声明

例如上面例子所示的

import { ref } from 'vue'
const name = ref('Vue')

父子组件通信的实现

经过上面的一系列对setup的介绍,相信对这个新的语法糖也有大概的印象啦,接下来会详细介绍在<script setup>下实现组件通信

Vue3中.sync语法的废弃

在很多业务需求中,我们需要对父组件传入子组件的prop值进行「双向绑定」,相信大家如果在Vue2中是使用.sync这个语法糖实现,但是如果在Vue3里继续使用.sync的语法糖,eslint就会提示该语法糖已经被废弃了的错误,vue/no-deprecated-v-bind-sync

image.png

因此我们需要对其进行改造

使用v-model进行父子组件的值双向绑定

  • 使用v-model对该值进行双向绑定,先把代码呈上
// Father.vue
<template>
    <ChildrenComponent v-model="fatherData"/>
</template>
<script setup>
import { ref } from 'vue'
import ChildrenComponent from './components/ChildrenComponent.vue'
const fatherData = ref('这是父组件的值,要传进去给子组件的')
</script>

接下来是子组件的代码

// ChildrenComponent.vue
<template>
    <div>click me</div>
    <div>当前父组件要显示的值:</div>
    <div>{{ modelValue }}</div>
</template>
<script setup lang='ts'>
interface Props {
    modelValue: string
}
const props = withDefaults(defineProps<Props>(), {
    modelValue: '子组件里默认的值'
})
</script>

在语法糖setup里,defineProps,withDefaultsdefineEmits中的编译器宏,因此不需要额外引入,可以直接使用

这里有个小知识点:如果不想用modelValue这个默认的props名字,可以自己声明定义,例如v-model:selfDefine,那么在子组件里的props就可以传selfDefine啦

// Father.vue
...
<ChildrenComponent v-model:selfDefine="fatherData"/>
...
// ChildrenComponent.vue
<script setup lang='ts'>
interface Props {
    selfDefine: string
}
const props = withDefaults(defineProps<Props>(), {
    selfDefine: '子组件里默认的值'
})
</script>

就是这么的简单!!快看,这个作者是真心想你们学会的!!

使用defineEmits子组件修改父组件传的值

在Vue2中是使用this.$emit('update:modelValue', '子组件传给父组件的最新值'),但是由于在<script setup>里是没有this,因此我们使用defineEmits()代替,我们修改一下上面的子组件的代码

// ChildrenComponent.vue
<template>
    <div @click="updateValue">click me</div>
    <div>当前父组件要显示的值:</div>
    <div>{{ modelValue }}</div>
</template>
<script setup lang='ts'>
interface Props {
    modelValue: string
}
const props = withDefaults(defineProps<Props>(), {
    modelValue: '子组件里默认的值'
})

const emit = defineEmits(['update:modelValue']);
const updateValue = () => {
    emit('update:modelValue', '传一个新的值')
}
</script>

使用defineEmits注册update:modelValue事件,然后点击一下click按钮就可以触发到父组件值的更新了

结语

以上是我使用Vue3对父子组件通信的实践,希望能对大家有帮助~如果能获得一个大大的赞❤作为鼓励会十分感激😄!!大家也可以多在评论区交流讨论哦,谢谢啦~

更多文章推荐:

「超详细!监听微信小程序五种切后台情况」

「HTTP响应头之内容安全策略(CSP)为你的网站保驾护航」

「不再迷茫!看了这篇文章让你上手Vue3.0开发有丝滑般体验」

「三分钟学会使用requestAnimationFrame实现倒计时」

「欢迎在评论区讨论,掘金官方将在掘力星计划活动结束后,在评论区抽送100份掘金周边,抽奖详情见活动文章」