vue3 组件传参的方式

560 阅读1分钟

在 Vue 3 中,组件传参的方式有多种,常见的方式包括

  1. propsemit
  2. v-modelprovide/injectref/defineExpose
  3. 下面分别介绍:

方式一:propsemit

<!-- 父组件 -->
<script setup>
import ChildComponent from './ChildComponent.vue';
const message = 'Hello from parent';

const handleUpdate = (newMessage) => {
    console.log(`子组件传递的参数为:${newMessage}`)
};
</script>

<template>
  <ChildComponent :msg="message" @updateMessage="handleUpdate"/>
</template>

<!-- 子组件 -->
<script setup>
import { defineEmits } from 'vue';
defineProps({
  msg: String
});
const emit = defineEmits(['updateMessage']); 
const sendMessage = () => { 
    emit('updateMessage', 'Hello from child'); 
};
</script>

<template>
  <p>{{ msg }}</p>
  <button @click="sendMessage">发送消息</button>
</template>

方式二:provide/inject

provide 和 inject 允许祖先组件向所有子孙组件传递数据,而不需要通过每一层组件手动传递。

//1.  在`父组件/根组件`中定义`provide`,**提供数据**。
<script setup> 
    import { ref, provide } from 'vue'; 
    const name = ref('sam'); 
    provide('name', name)
</script>
//2. 在`子组件/孙子组件`中使用`inject`,**注入数据**。
<script setup> 
    import { inject } from 'vue'; 
    const name = inject('name'); 
    console.log('name:', name.value); //输出name:sam
</script>

方式三:兄弟组件通信 (Mitt)

对于兄弟组件之间的通信,我们可以使用第三方库 mitt 来实现一个简单的事件总线。

首先,安装 mitt:

npm install --save mitt

然后,在 main.js 中全局配置:

import { createApp } from 'vue'
import mitt from 'mitt'
import App from './App.vue'
 
const app = createApp(App)
app.config.globalProperties.$bus = mitt()
app.mount('#app')

「发送事件的组件:」

<script setup>
import { getCurrentInstance } from 'vue'
const { proxy } = getCurrentInstance()
const sendMessage = () => {
  proxy.$bus.emit('myEvent', 'Hello world');
}
</script>

「接收事件的组件:」

<script setup>
import { onMounted, getCurrentInstance } from 'vue'
const { proxy } = getCurrentInstance()
onMounted(() => {
  proxy.$bus.on('myEvent', (message) => {
    console.log(message) // 输出: "Hello world"
  })
})
</script>

方式四:透传 Attributes ($attrs)

$attrs 包含了父组件传递给子组件的所有属性,除了那些已经被 props 或 emits 声明的。

//父组件
<template>
  <child name="小明" age="18" hobby="篮球"></child>
</template>

//子组件
<script setup>
  import { useAttrs } from 'vue'
  const attrs = useAttrs()
  console.log(attrs) // { age: "18", hobby: "篮球" }
</script>

方式五:模板引用 (Refs)

通过 ref,父组件可以直接访问子组件的属性和方法。

//父组件
<template>
  <child ref="childRef"></child>
  <button @click="callChildMethod">调用子组件方法</button>
</template>
 
<script setup>
    import { ref } from 'vue'
    import Child from './Child.vue'
    const childRef = ref(null)
    const callChildMethod = () => {
      childRef.value.someMethod()
    }
</script>
//子组件
<script setup>
    import { defineExpose } from 'vue'
    const someMethod = () => {
      console.log('子组件方法被调用了')
    }
    defineExpose({
      someMethod,
    })
</script>

方式六:双向绑定 (v-model)

v-model 提供了一种简洁的方式来实现父子组件之间的双向数据绑定。

//父组件
<template>
  <child v-model:name="name"></child>
</template>
 
<script setup>
  import { ref } from 'vue'
  import Child from './Child.vue'
 
  const name = ref('小明')
</script>
//子组件
<template>
  <input :value="name" @input="updateName" />
</template>
<script setup>
  import { defineProps, defineEmits } from 'vue'
  const props = defineProps(['name'])
  const emit = defineEmits(['update:name'])
  const updateName = (e) => {
    emit('update:name', e.target.value)
  }
</script>

方式七:状态管理

  • Pinia 是新一代的 Vue 状态管理库,提供更简单的 API 和更好的 TypeScript 支持
  • Vuex 是 Vue 的官方状态管理库,适用于大型应用。

方式八:浏览器存储

localStorage 和 sessionStorage 可以用于在不同页面或组件之间共享数据。

方式九:全局属性

// main.js
const app = createApp(App)
app.config.globalProperties.$http = axios
// 在组件中使用
import { getCurrentInstance } from 'vue'
const { proxy } = getCurrentInstance()
proxy.$http.get('/api/data')