Vue3组件通信:父子相传

父传子

父传子是通过props(组件上自定义的attribute。子组件注册attribute,父组件给这些attribute赋值,子组件通过对应的attribute名称获取对应的值) 来完成组件之间的通信

Props

  1. 数组用法
  • 数组中的字符串就是attribute的名称
xml 复制代码
<template>
  <div class="card-container">
    <div class="card-header">
      <div class="card-title">{{ title }}</div>
      <div v-if="showBackBtn">aaa</div>
    </div>
    <div class="card-content">
      <slot></slot>
    </div>
  </div>
</template>

<script setup>
const props = defineProps(["title","showBackBtn"])
</script>
xml 复制代码
<template><ContentCard title="状态修改" :showBackBtn="true"> </ContentCard></template>

<script setup>
import ContentCard from '@/components/admin/ContentCard.vue'
</script>
  1. 对象用法
  • 可以对传入的内容进行限制(指定传入的attribute的类型,是否必传,默认值)
xml 复制代码
<template>
  <div class="card-container">
    <div class="card-header">
      <div class="card-title">{{ title }}</div>
      <button v-if="showBackBtn" @click="handleBack" class="back-button">
        <el-icon :size="18"><Back /></el-icon>返回
      </button>
    </div>
    <div class="card-content">
      <slot></slot>
    </div>
  </div>
</template>

<script setup>
import { useRouter } from 'vue-router'
import { Back } from '@element-plus/icons-vue'

const { title, showBackBtn } = defineProps({
  title: {
    type: String,
    required: true,
  },
  showBackBtn: {
    type: Boolean,
    default: false,
  },
})

const router = useRouter()
const handleBack = () => router.go(-1)
</script>
xml 复制代码
<template><ContentCard title="状态修改"> </ContentCard></template>

<script setup>
import ContentCard from '@/components/admin/ContentCard.vue'
</script>

非Prop的Attribute

传递给子组件的某些个属性,这些属性不在子组件的props和emits里面

常见class、style、id

  1. 若组件有单个根节点,非prop的attribute会自动添加到根节点的attribute中(继承)
  1. 禁用attribute继承和多个根节点情况
  • 组件中设置inheritAttrs:false可以禁用根组件自动attribute继承,我们可以在子组件中使用$attrs来访问非Prop的Attribute
xml 复制代码
<template>
  <div class="card-container">
    <div class="card-header">
      <div class="card-title">{{ title }}</div>
      <div v-if="showBackBtn">aaa</div>
    </div>
    <div :class="$attrs.class">
      <slot></slot>
    </div>
  </div>
</template>

<script setup>
const props = defineProps(["title","showBackBtn"])
</script>
  • 若组件有多个根节点且没有显示绑定,此时会报警告,需手动绑定
xml 复制代码
<template>
    <div class="card-header">
      <div class="card-title">{{ title }}</div>
      <div v-if="showBackBtn">aaa</div>
    </div>
    <div :class="$attrs.class">
      <slot></slot>
    </div>
</template>

<script setup>
const props = defineProps(["title","showBackBtn"])
</script>

子传父

  1. 子组件defineEmits()定义可以触发并且被父组件监听的事件
  2. 父组件@+子组件定义的事件名监听该事件
  3. 当子组件使用emit()触发某事件时,父组件监听到该事件被触发,便执行父组件里该事件对应的逻辑
xml 复制代码
<template>
  <div class="child">
    <h3>子组件</h3>
    <button @click="sendData">向父组件传递数据</button>
  </div>
</template>

<script setup>
import { defineEmits } from 'vue'
// 定义可以触发的事件
const emit = defineEmits(['send-message'])
// 子组件发送数据的方法
const sendData = () => {
  // 可以是任意类型的数据:字符串、数字、对象等
  const message = "Hello 父组件,这是子组件发送的数据!"
  const count = 100
  
  // 通过emit触发事件,传递数据给父组件
  emit('send-message', message, count)
}
</script>
xml 复制代码
<template>
  <div class="parent">
    <h2>父组件</h2>
    <p>子组件传递的消息:{{ receivedMessage }}</p>
    <p>子组件传递的数字:{{ receivedCount }}</p>
    <!-- 引入子组件并监听事件 -->
    <ChildComponent @send-message="handleMessage" />
  </div>
</template>

<script setup>
import { ref } from 'vue'
import ChildComponent from './ChildComponent.vue'

// 父组件用于存储接收的数据
const receivedMessage = ref('')
const receivedCount = ref(0)

// 处理子组件传递过来的数据
const handleMessage = (msg, count) => {
  receivedMessage.value = msg
  receivedCount.value = count
}
</script>

Tips

  • 父传子时,当需要传递 非字符串数据(如布尔值、数字、对象、数组等)时,必须加 :,只有传递纯字符串时可以省略
  • 在Vue 3的<script setup>语法中,当我们使用defineProps定义props后,Vue会自动将props解构到当前作用域中,所以我们可以直接使用title而不是props.title
  • HTML 中的 attribute 名是大小写不敏感的,所以浏览器会把所有大写字符解释为小写字符。这意味着当你使用 DOM 中的模板时,camelCase (驼峰命名法) 的 prop 名需要使用其等价的 kebab-case (短横线分隔命名) 命名
xml 复制代码
<template><ContentCard title="状态修改" :show-back-btn="ture"> </ContentCard></template>

<script setup>
import ContentCard from '@/components/admin/ContentCard.vue'
</script>
相关推荐
追风筝的人er2 小时前
SpringBoot+Vue3 企业考勤如何处理法定假期?节假日方案、调休补班与工作日判断链路拆解
前端·vue.js·后端
编程老船长5 小时前
解决不同项目需要不同 Node.js 版本的问题
前端·vue.js
xiaogg36787 小时前
spring oauth2 单点登录
java·vue.js·spring
前端那点事8 小时前
Vue前端SEO优化全攻略(实操落地版,新手也能上手)
前端·vue.js
计算机学姐8 小时前
基于微信小程序的校园失物招领管理系统【uniapp+springboot+vue】
java·vue.js·spring boot·mysql·信息可视化·微信小程序·uni-app
fix一个write十个9 小时前
从零搭建音视频通话太痛苦?这个 Vue3 CallKit 让你 5 分钟搞定 1v1 + 群聊通话
前端·vue.js·github
小歪 | 前端10 小时前
VUE_运行Vue项目Network: unavailable问题解决
前端·javascript·vue.js
计算机学姐11 小时前
基于微信小程序的宠物服务系统【uniapp+springboot+vue】
java·vue.js·spring boot·mysql·微信小程序·uni-app·宠物
钱端工程师11 小时前
vue自定义一个在线查看文件的组件(.xlsx、.docx、.pdf、图片等)
javascript·vue.js·pdf
涵涵(互关)12 小时前
GoView各项目文件中的相关语法3
前端·vue.js·typescript