小知识,大挑战!本文正在参与「程序员必备小知识」创作活动
本文已参与「掘力星计划」,赢取创作大礼包,挑战创作激励金
前言:最近在做一个项目技术栈是选用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
因此我们需要对其进行改造
使用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,withDefaults和defineEmits中的编译器宏,因此不需要额外引入,可以直接使用
这里有个小知识点:如果不想用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份掘金周边,抽奖详情见活动文章」