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>
相关推荐
岁月宁静15 小时前
深度定制:在 Vue 3.5 应用中集成流式 AI 写作助手的实践
前端·vue.js·人工智能
百锦再16 小时前
Vue Scoped样式混淆问题详解与解决方案
java·前端·javascript·数据库·vue.js·学习·.net
Sheldon一蓑烟雨任平生17 小时前
Vue3 表单输入绑定
vue.js·vue3·v-model·vue3 表单输入绑定·表单输入绑定·input和change区别·vue3 双向数据绑定
YUELEI11819 小时前
Vue 安装依赖的集合和小知识
javascript·vue.js·ecmascript
前端付豪20 小时前
万事从 todolist 开始
前端·vue.js·前端框架
华仔啊21 小时前
别再纠结Pinia和Vuex了!一篇文章彻底搞懂区别与选择
前端·vue.js
月弦笙音1 天前
【Vue3】Keep-Alive 深度解析
前端·vue.js·源码阅读
咖啡の猫1 天前
Vue 实例生命周期
前端·vue.js·okhttp
JNU freshman1 天前
vue 之 import 的语法
前端·javascript·vue.js
剑亦未配妥1 天前
Vue 2 响应式系统常见问题与解决方案(包含_demo以下划线开头命名的变量导致响应式丢失问题)
前端·javascript·vue.js