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>
相关推荐
anyup16 分钟前
🔥🔥 10 天 Star 破百!uView Pro 文档也开源啦:完全免费、无广告、高效上手
前端·vue.js·uni-app
南半球与北海道#1 小时前
el-table合并单元格
javascript·vue.js·elementui·表格合并
啷咯哩咯啷2 小时前
element-plus el-tree-v2大数据量勾选节点卡顿问题
前端·javascript·vue.js
索西3 小时前
Vue 响应式原理
vue.js
Sky_Ax3 小时前
实现一个时间轴组件
vue.js
RainbowSea5 小时前
伙伴匹配系统(移动端 H5 网站(APP 风格)基于Spring Boot 后端 + Vue3 - 05
vue.js·spring boot·后端
文艺理科生5 小时前
Nuxt 组件渲染进阶:服务端与客户端组件的协作艺术
前端·javascript·vue.js
天客5 小时前
Vue3.5 + Element-Plus 二次封装 el-table、el-form、el-descriptions
前端·vue.js
XiaoMu_0016 小时前
【Vue vs React:前端框架深度对比分析】
vue.js·react.js·前端框架