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>
相关推荐
jaychouchannel7 小时前
深入理解 Vue 3 Composition API:为什么它是现代前端的必修课
vue.js
笔优站长7 小时前
从 Vue 2 到 Vue 3:我把 vue-aliplayer-v2 重构成了一个更现代的阿里云播放器组件
前端·vue.js
i_am_a_div_日积月累_9 小时前
3.contextBridge桥梁
前端·javascript·vue.js·electron
bug-1008610 小时前
hooks,mixin,pinia,vuex
前端·vue.js
bug-1008610 小时前
vue2和vue3的路由变化
前端·vue.js
狼丶宇先森11 小时前
vue-sign-canvas v2 重构复盘:从 Vue 2 签名板到 Vue 3 + TypeScript 组件库
前端·vue.js·重构·typescript·开源软件·canvas
bug-1008611 小时前
为什么history模式默认会请求后端资源?
前端·vue.js·nginx
星星~笑笑11 小时前
vue 超简单 oss分片上传文件 大文件上传阿里云
前端·javascript·vue.js·uni-app
PieroPc12 小时前
通用产品标签打印 (为制衣厂 打印纸箱错印或不足 补打修改纸箱通用程序)html版
前端·javascript·vue.js
弹简特12 小时前
【Vue3速成】03-vue基本语法的使用
前端·javascript·vue.js