在 Vue 項目中,組件間的引用與數據交互是核心功能之一。以下是組件引用和數據交互的詳細實現方式及示例:
一、組件引用方式
1. 基本組件引用
- 局部注冊:在父組件中按需引入子組件并注冊。
// ParentComponent.vue
import ChildComponent from './ChildComponent.vue'export default {components: {ChildComponent},template: `<ChildComponent :message="msg" @update="handleUpdate" />`
}
- 全局注冊:在主入口文件中統一注冊,所有組件均可使用。
// main.js
import { createApp } from 'vue'
import App from './App.vue'
import GlobalComp from './components/GlobalComp.vue'const app = createApp(App)
app.component('GlobalComp', GlobalComp)
app.mount('#app')
2. 動態組件加載
<!-- DynamicComponent.vue -->
<template><component :is="currentView"></component>
</template><script>
import Home from './Home.vue'
import About from './About.vue'export default {data() {return {currentView: 'Home'}},components: { Home, About }
}
</script>
二、組件間數據交互方式
1. Props & $emit(父子組件通信)
- 父 → 子:通過
props
傳遞數據。 - 子 → 父:通過
$emit
觸發自定義事件。
示例:
<!-- Parent.vue -->
<template><div><Child :count="counter" @increment="addCount" /></div>
</template><script>
import Child from './Child.vue'export default {data() {return { counter: 0 }},methods: {addCount() {this.counter += 1}}
}
</script>
<!-- Child.vue -->
<template><button @click="increment">Click Me: {{ count }}</button>
</template><script>
export default {props: ['count'],methods: {increment() {this.$emit('increment') // 通知父組件}}
}
</script>
2. provide/inject
(任意層級組件通信)
用于祖先組件直接向后代組件傳遞數據,無需逐層傳遞。
示例:
<!-- Ancestor.vue -->
<template><div><Descendant /></div>
</template><script>
import Descendant from './Descendant.vue'export default {provide() {return {sharedState: this.state}},data() {return { state: 'from Ancestor' }}
}
</script>
<!-- Descendant.vue -->
<template><div>{{ injectedData }}</div>
</template><script>
export default {inject: ['sharedState'],computed: {injectedData() {return this.sharedState}}
}
</script>
3. Vuex(復雜狀態管理)
適用于多組件共享狀態的場景。
安裝與配置:
npm install vuex@next
// store.js
import { createStore } from 'vuex'export const store = createStore({state() {return { count: 0 }},mutations: {increment(state) {state.count++}}
})
<!-- Counter.vue -->
<template><div>{{ $store.state.count }}<button @click="$store.commit('increment')">Increment</button></div>
</template>
4. 事件總線(Event Bus)
用于非父子組件間的輕量級通信(Vue 3 推薦使用 mitt
替代)。
示例:
// eventBus.js
import mitt from 'mitt'
const emitter = mitt()
export default emitter
<!-- Sender.vue -->
<script>
import emitter from './eventBus'emitter.emit('notify', { message: 'Hello!' })
</script>
<!-- Receiver.vue -->
<script>
import emitter from './eventBus'emitter.on('notify', (data) => {console.log(data.message)
})
</script>
三、完整示例:計數器應用
1. 項目結構
src/
├── components/
│ ├── CounterDisplay.vue
│ └── IncrementButton.vue
├── App.vue
└── main.js
2. 代碼實現
<!-- App.vue -->
<template><div><CounterDisplay :count="counter" /><IncrementButton @increment="counter++" /></div>
</template><script>
import CounterDisplay from './components/CounterDisplay.vue'
import IncrementButton from './components/IncrementButton.vue'export default {data() {return { counter: 0 }},components: { CounterDisplay, IncrementButton }
}
</script>
<!-- CounterDisplay.vue -->
<template><h1>Count: {{ count }}</h1></template>
<script>
export default {props: ['count']
}
</script>
<!-- IncrementButton.vue -->
<template><button @click="$emit('increment')">+1</button></template>
四、注意事項
- Prop 單向數據流:子組件不應直接修改父組件傳遞的
props
。 - 事件命名規范:使用
kebab-case
命名自定義事件(如update:field
)。 - 性能優化:避免過度使用全局狀態管理(如 Vuex),優先選擇組件間直接通信。
通過以上方式,可以實現靈活高效的組件引用與數據交互!