Vue3组件间通信

本文详细介绍了Vue.js中组件间通信的几种常见方式,包括父传子(Props)、子传父(emits)、子传父(expose/ref)以及祖孙多层组件通信(provide/inject)。通过实例代码展示了如何在不同场景下实现数据和方法的传递,帮助开发者理解Vue.js组件通信的机制。
父传子(Props)
// Parent.vue

<template>
  <!-- 使用子组件 -->
  <Child :msg="message" />
</template>

<script setup>
import Child from './components/Child.vue' // 引入子组件

let message = '雷猴'
</script>
// Child.vue

<template>
  <div>
    {{ msg }}
  </div>
</template>

<script setup>

const props = defineProps({
  msg: {
    type: String,
    default: ''
  }
})

//另一种写法
//  const props = defineProps<{
//    msg:String
//  }>();

//这一步很关键哦,为了页面响应式,需要toRefs一下
const {msg} = toRefs(props)

</script>
子传父(emits)

子组件通知父组件触发一个事件,并且可以传值给父组件。

// Parent.vue

<template>
  <div>父组件:{{ message }}</div>
  <!-- 自定义 changeMsg 事件 -->
  <Child @changeMsg="changeMessage" />
</template>

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

let message = ref('雷猴')

// 更改 message 的值,data是从子组件传过来的
function changeMessage(data) {
  message.value = data
}
</script>
// Child.vue

<template>
  <div>
    子组件:<button @click="handleClick">子组件的按钮</button>
  </div>
</template>

<script setup>

// 注册一个自定义事件名,向上传递时告诉父组件要触发的事件。
const emit = defineEmits(['changeMsg'])

function handleClick() {
  // 参数1:事件名
  // 参数2:传给父组件的值
  emit('changeMsg', '鲨鱼辣椒')
}

</script>
子传父(expose / ref)

子组件可以通过 expose 暴露自身的方法和数据。

父组件通过 ref 获取到子组件并调用其方法或访问数据。

// Parent.vue

<template>
  <div>父组件:拿到子组件的message数据:{{ msg }}</div>
  <button @click="callChildFn">调用子组件的方法</button>

  <hr>

  <Child ref="com" />
</template>

<script setup>
import { ref, onMounted } from 'vue'
import Child from './components/Child.vue'

const com = ref(null) // 通过 模板ref 绑定子组件

const msg = ref('')

onMounted(() => {
  // 在加载完成后,将子组件的 message 赋值给 msg
  msg.value = com.value.message
})

function callChildFn() {
  // 调用子组件的 changeMessage 方法
  com.value.changeMessage('蒜头王八')

  // 重新将 子组件的message 赋值给 msg
  msg.value = com.value.message
}
</script>
// Child.vue

<template>
  <div>子组件:{{ message }}</div>
</template>

<script setup>
import { ref } from 'vue'

const message = ref('蟑螂恶霸')

function changeMessage(data) {
  message.value = data
}

使用 defineExpose 向外暴露指定的数据和方法
defineExpose({
  message,
  changeMessage
})

</script>
祖孙多层组件通信(provide/inject)
// Parent.vue

<template>
  <Child></Child>
</template>

<script setup>
import { ref, provide, readonly } from 'vue'
import Child from './components/Child.vue'

const name = ref('猛虎下山')
const msg = ref('雷猴')

// 使用readonly可以让子组件无法直接修改,需要调用provide往下传的方法来修改
provide('name', readonly(name))

provide('msg', msg)

provide('changeName', (value) => {
  name.value = value
})
</script>
// Child.vue

<template>
  <div>
    <div>msg: {{ msg }}</div>
    <div>name: {{name}}</div>
    <button @click="handleClick">修改</button>
  </div>
</template>

<script setup>
import { inject } from 'vue'

const name = inject('name', 'hello') // 看看有没有值,没值的话就适用默认值(这里默认值是hello)
const msg = inject('msg')
const changeName = inject('changeName')

function handleClick() {
  // 这样写不合适,因为vue里推荐使用单向数据流,当父级使用readonly后,这行代码是不会生效的。没使用之前才会生效。
  // name.value = '雷猴'

  // 正确的方式
  changeName('虎躯一震')

  // 因为 msg 没被 readonly 过,所以可以直接修改值
  msg.value = '世界'
}
</script>
### 三级标题:组件间通信的基本概念 在 Vue3 中,组件间通信是构建复杂应用的核心部分。常见的组件间通信方式包括使用 `props`、`ref` 和 `emit` 等方法。这些方法分别适用于不同的场景,例如父子组件通信、兄弟组件通信以及跨层级组件通信。 ### 三级标题:使用 props 进行父传子通信 `props` 是一种单向数据流的方式,用于将数据从父组件传递到子组件。在 Vue3 中,可以使用 `script setup` 或 `composition API` 来定义和接收 `props`。 ```vue <!-- 子组件 --> <script setup> const props = defineProps({ message: { type: String, default: &#39;默认值&#39; } }); </script> <template> <p>{{ message }}</p> </template> ``` ```vue <!-- 父组件 --> <script setup> import ChildComponent from &#39;./ChildComponent.vue&#39;; import { ref } from &#39;vue&#39;; const parentMessage = ref(&#39;来自父组件的消息&#39;); </script> <template> <ChildComponent :message="parentMessage" /> </template> ``` 通过这种方式,父组件可以将数据传递给子组件,并且子组件可以根据需要显示或处理这些数据[^4]。 ### 三级标题:使用 ref 获取子组件实例 在 Vue3 中,`ref` 可以用于获取 DOM 元素或组件的实例。通过 `ref`,父组件可以直接访问子组件的数据和方法。 ```vue <!-- 父组件 --> <script setup> import { ref, onMounted } from &#39;vue&#39;; import ChildComponent from &#39;./ChildComponent.vue&#39;; const childRef = ref(); onMounted(() => { console.log(childRef.value.str); // 访问子组件的数据 childRef.value.fn(&#39;调用了子组件的方法&#39;); // 调用子组件的方法 }); </script> <template> <ChildComponent ref="childRef" /> </template> ``` ```vue <!-- 子组件 --> <script setup> import { ref } from &#39;vue&#39;; const str = ref(&#39;我是数据&#39;); function fn(e) { console.log(e); } defineExpose({ str, fn }); // 暴露子组件的数据和方法 </script> <template> <input type="text" /> </template> ``` 通过 `ref`,父组件可以访问子组件的内部状态和方法,从而实现更灵活的交互[^2]。 ### 三级标题:结合 props 和 ref 的使用场景 在实际开发中,`props` 和 `ref` 可以结合使用来满足复杂的业务需求。例如,父组件可以通过 `props` 向子组件传递配置信息,并通过 `ref` 控制子组件的行为。 ```vue <!-- 父组件 --> <script setup> import { ref } from &#39;vue&#39;; import ChildComponent from &#39;./ChildComponent.vue&#39;; const childRef = ref(); const config = { title: &#39;子组件标题&#39;, color: &#39;blue&#39; }; </script> <template> <ChildComponent :config="config" ref="childRef" /> </template> ``` ```vue <!-- 子组件 --> <script setup> import { defineProps, defineExpose } from &#39;vue&#39;; const props = defineProps([&#39;config&#39;]); const str = &#39;子组件数据&#39;; function updateData(newData) { console.log(&#39;更新数据:&#39;, newData); } defineExpose({ str, updateData }); // 暴露子组件的数据和方法 </script> <template> <div :style="{ color: config.color }">{{ config.title }}</div> </template> ``` 通过这种方式,父组件不仅可以传递配置信息,还可以直接调用子组件的方法来更新数据或执行其他操作。 ### 三级标题:注意事项 1. **避免滥用 `ref`**:虽然 `ref` 提供了强大的功能,但应谨慎使用,因为过度依赖 `ref` 可能会导致代码难以维护。 2. **保持单向数据流**:尽量遵循 Vue 的单向数据流原则,避免直接修改 `props`,而是通过事件机制进行通信3. **合理暴露子组件方法**:使用 `defineExpose` 时,只暴露必要的数据和方法,以减少耦合度。 通过合理使用 `props` 和 `ref`,可以有效地实现 Vue3 中的组件间通信,提高应用的灵活性和可维护性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值