目录
一、常用
Props
父组件:
子组件:
$emit和$on
父组件:
子组件:
$parent和$children
父组件:
子组件:
$attrs和$listeners
父组件:
子组件:
provide和inject
父组件:
子组件:
二、其他探索
EventBus
父组件:
子组件:
Vuex
store.js:
父组件:
子组件:
$refs属性
父组件:
子组件:
$parent属性
父组件:
子组件:
$root属性
根组件:
子组件:
provide / inject (高级)
祖先组件:
直接子组件:
间接子组件:
provide / inject + Vuex (高级)
根组件:
子组件和孙组件:
自定义事件
父组件:
子组件:
兄弟组件之间的通信
EventBus.js:
组件A:
组件B:
localStorage(浏览器缓存)
组件A:
组件B:
发布订阅(Pub/Sub)模式
消息中心:
组件A:
组件B:
WebSocket (高级)
连接WebSocket服务器:
组件A:
组件B:
路由参数(高级)
父组件:
子组件:
兄弟组件:
Vuex状态管理(高级)
store.js:
组件A:
组件B:
事件总线(高级)
事件总线:
组件A:
组件B:
三、往期优质推荐
一、常用
- 最近一直在封装各种组件, 提高组员开发效率,
- 遇到了各种情况下的父子组件, 兄弟组件之间各种传值,
- 这里做下总结和一些探索, 欢迎补充~
Props
父组件向子组件传递数据,子组件通过props属性接收数据
父组件:
<template>
<div>
<child-component :parentData="data"></child-component>
</div>
</template>
<script>
import ChildComponent from './ChildComponent.vue'
export default {
components: {
ChildComponent
},
data () {
return {
data: '父组件传递的数据'
}
}
}
</script>
子组件:
<template>
<div>
子组件接收到的数据:{{ parentData }}
</div>
</template>
<script>
export default {
props: {
parentData: String
}
}
</script>
Vue props默认值类型有哪些
$emit和$on
子组件向父组件传递数据,子组件通过$emit触发事件,父组件通过$on监听事件并接收数据。
父组件:
<template>
<div>
<child-component @childEvent="handleChild"></child-component>
</div>
</template>
<script>
import ChildComponent from './ChildComponent.vue'
export default {
components: {
ChildComponent
},
methods: {
handleChild (data) {
console.log('父组件接收到的数据:' + data)
}
}
}
</script>
子组件:
<template>
<div>
<button @click="handleClick">点击触发事件</button>
</div>
</template>
<script>
export default {
methods: {
handleClick () {
this.$emit('childEvent', '子组件传递的数据')
}
}
}
</script>
$parent和$children
父组件向子组件传递数据,父组件通过$children获取子组件实例并调用子组件方法传递数据。
父组件:
<template>
<div>
<button @click="handleClick">向子组件传递数据</button>
<child-component ref="child"></child-component>
</div>
</template>
<script>
import ChildComponent from './ChildComponent.vue'
export default {
components: {
ChildComponent
},
methods: {
handleClick () {
this.$refs.child.handleData('父组件传递的数据')
}
}
}
</script>
子组件:
<template>
<div>
子组件
</div>
</template>
<script>
export default {
methods: {
handleData (data) {
console.log('子组件接收到的数据:' + data)
}
}
}
</script>
$attrs和$listeners
父组件向子组件传递属性和事件,子组件通过$attrs获取属性,通过$listeners获取事件并绑定在子组件上。
父组件:
<template>
<div>
<child-component attr1="属性1" attr2="属性2" @event1="handleEvent"></child-component>
</div>
</template>
<script>
import ChildComponent from './ChildComponent.vue'
export default {
components: {
ChildComponent
},
methods: {
handleEvent (data) {
console.log('父组件接收到的数据:' + data)
}
}
}
</script>
子组件:
<template>
<div>
子组件
</div>
</template>
<script>
export default {
mounted () {
this.$emit('event1', '子组件传递的数据')
}
}
</script>
provide和inject
父组件向子组件传递数据,父组件通过provide提供数据,子组件通过inject注入数据。
父组件:
<template>
<div>
<child-component></child-component>
</div>
</template>
<script>
import ChildComponent from './ChildComponent.vue'
export default {
components: {
ChildComponent
},
provide () {
return {
parentData: '父组件提供的数据'
}
}
}
</script>
子组件:
<template>
<div>
子组件接收到的数据:{{ childData }}
</div>
</template>
<script>
export default {
inject: ['parentData'],
computed: {
childData () {
return this.parentData + ',子组件加工处理后的数据'
}
}
}
</script>
二、其他探索
EventBus
父组件和子组件之间通过中央事件总线(EventBus)进行通信。
EventBus.js:
import Vue from 'vue'
export const EventBus = new Vue()
父组件:
<template>
<div>
<button @click="handleParent">向子组件传递数据</button>
<child-component></child-component>
</div>
</template>
<script>
import ChildComponent from './ChildComponent.vue'
import { EventBus } from './EventBus'
export default {
components: {
ChildComponent
},
methods: {
handleParent () {
EventBus.$emit('parent-event', '父组件传递的数据')
}
}
}
</script>
子组件:
<template>
<div>
子组件接收到的数据:{{ childData }}
</div>
</template>
<script>
import { EventBus } from './EventBus'
export default {
data () {
return {
childData: ''
}
},
mounted () {
EventBus.$on('parent-event', data => {
this.childData = data
})
}
}
</script>
Vuex
父组件和子组件之间通过Vuex进行通信,共享同一状态树。
store.js:
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
data: '共享的数据'
},
mutations: {
setData (state, data) {
state.data = data
}
}
})
父组件:
<template>
<div>
<button @click="handleParent">向子组件传递数据</button>
<child-component></child-component>
</div>
</template>
<script>
import ChildComponent from './ChildComponent.vue'
import store from './store'
export default {
components: {
ChildComponent
},
methods: {
handleParent () {
store.commit('setData', '父组件传递的数据')
}
}
}
</script>
子组件:
<template>
<div>
子组件接收到的数据:{{ childData }}
</div>
</template>
<script>
import { mapState } from 'vuex'
export default {
computed: {
...mapState(['data']),
childData () {
return this.data + ',子组件加工处理后的数据'
}
}
}
</script>
$refs属性
父组件可以通过$refs获取子组件的实例,进而访问子组件的属性和方法。
父组件:
<template>
<div>
<button @click="handleParent">向子组件传递数据</button>
<child-component ref="child"></child-component>
</div>
</template>
<script>
import ChildComponent from './ChildComponent.vue'
export default {
components: {
ChildComponent
},
methods: {
handleParent () {
this.$refs.child.childData = '父组件修改的数据'
}
}
}
</script>
子组件:
<template>
<div>
子组件接收到的数据:{{ childData }}
</div>
</template>
<script>
export default {
data () {
return {
childData: '子组件原始数据'
}
}
}
</script>
$parent属性
子组件可以通过$parent获取父组件的实例,进而访问父组件的属性和方法。
父组件:
<template>
<div>
<child-component></child-component>
</div>
</template>
<script>
import ChildComponent from './ChildComponent.vue'
export default {
components: {
ChildComponent
},
data () {
return {
parentData: '父组件数据'
}
},
methods: {
handleParent () {
console.log('父组件的方法')
}
}
}
</script>
子组件:
<template>
<div>
<button @click="handleChild">调用父组件方法</button>
</div>
</template>
<script>
export default {
methods: {
handleChild () {
console.log(this.$parent.parentData)
this.$parent.handleParent()
}
}
}
</script>
$root属性
子组件可以通过$root获取根组件的实例,进而访问根组件的属性和方法。
根组件:
<template>
<div>
<child-component></child-component>
</div>
</template>
<script>
import ChildComponent from './ChildComponent.vue'
export default {
components: {
ChildComponent
},
mounted () {
console.log('根组件的数据:' + this.rootData)
this.rootMethod()
},
data () {
return {
rootData: '根组件的数据'
}
},
methods: {
rootMethod () {
console.log('根组件的方法')
}
}
}
</script>
子组件:
<template>
<div>
子组件
</div>
</template>
<script>
export default {
mounted () {
console.log('根组件的数据:' + this.$root.rootData)
this.$root.rootMethod()
}
}
</script>
provide / inject (高级)
provide / inject 可以让祖先组件向所有后代组件注入一个依赖,让这些组件使用相同的依赖注入。
祖先组件:
<template>
<div>
<child-component></child-component>
<grand-child></grand-child>
</div>
</template>
<script>
import ChildComponent from './ChildComponent.vue'
import GrandChild from './GrandChild.vue'
export default {
components: {
ChildComponent,
GrandChild
},
provide: {
sharedObj: {
message: '这是祖先组件注入的对象'
}
}
}
</script>
直接子组件:
<template>
<div>
子组件
</div>
</template>
<script>
export default {
inject: ['sharedObj']
}
</script>
间接子组件:
<template>
<div>
子组件接收到的数据:{{ childData }}
</div>
</template>
<script>
export default {
inject: ['sharedObj'],
computed: {
childData () {
return this.sharedObj.message + ',子组件加工处理后的数据'
}
}
}
</script>
provide / inject + Vuex (高级)
使用provide / inject注入Vuex的实例,使所有组件使用相同的Vuex实例。
store.js:
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
data: '共享的数据'
},
mutations: {
setData (state, data) {
state.data = data
}
}
})
根组件:
<template>
<div>
<child-component></child-component>
</div>
</template>
<script>
import ChildComponent from './ChildComponent.vue'
import store from './store'
export default {
components: {
ChildComponent
},
provide () {
return {
store
}
}
}
</script>
子组件和孙组件:
<template>
<div>
组件接收到的数据:{{ componentData }}
</div>
</template>
<script>
export default {
inject: {
store: {
default: null
}
},
computed: {
componentData () {
return this.store.state.data + ',组件加工处理后的数据'
}
}
}
</script>
自定义事件
使用vm.$on(eventName, callback)
事件监听,使用vm.$emit(eventName, ...args)
触发事件。
父组件:
<template>
<div>
<child-component @custom-event="handleCustomEvent"></child-component>
</div>
</template>
<script>
import ChildComponent from './ChildComponent.vue'
export default {
components: {
ChildComponent
},
methods: {
handleCustomEvent (data) {
console.log('父组件接收到的数据:' + data)
}
}
}
</script>
子组件:
<template>
<div>
<button @click="handleClick">点击触发事件</button>
</div>
</template>
<script>
export default {
methods: {
handleClick () {
this.$emit('custom-event', '子组件传递的数据')
}
}
}
</script>
兄弟组件之间的通信
使用一个空的Vue实例作为事件总线,一边向事件总线发出事件,另一边监听事件。
EventBus.js:
import Vue from 'vue'
export const EventBus = new Vue()
组件A:
<template>
<div>
<button @click="handleClick">向组件B传递数据</button>
</div>
</template>
<script>
import { EventBus } from './EventBus'
export default {
methods: {
handleClick () {
EventBus.$emit('event', '组件A传递的数据')
}
}
}
</script>
组件B:
<template>
<div>
组件B接收到的数据:{{ data }}
</div>
</template>
<script>
import { EventBus } from './EventBus'
export default {
data () {
return {
data: ''
}
},
mounted () {
EventBus.$on('event', data => {
this.data = data
})
}
}
</script>
localStorage(浏览器缓存)
使用浏览器缓存来存储数据,在需要通信的组件中存储并监听缓存中的数据。
组件A:
<template>
<div>
<button @click="handleClick">向组件B传递数据</button>
</div>
</template>
<script>
export default {
methods: {
handleClick () {
localStorage.setItem('data', '组件A传递的数据')
}
}
}
</script>
组件B:
<template>
<div>
组件B接收到的数据:{{ data }}
</div>
</template>
<script>
export default {
data () {
return {
data: ''
}
},
mounted () {
window.addEventListener('storage', this.handleStorageUpdate)
this.updateData()
},
beforeDestroy () {
window.removeEventListener('storage', this.handleStorageUpdate)
},
methods: {
handleStorageUpdate (event) {
if (event.key === 'data') {
this.updateData()
}
},
updateData () {
this.data = localStorage.getItem('data') || ''
}
}
}
</script>
发布订阅(Pub/Sub)模式
使用一个消息中心,订阅者向消息中心订阅消息,发布者向消息中心发布消息,消息中心将消息通知给所有订阅者。
消息中心:
// PubSub.js
export const PubSub = {
events: {},
subscribe (event, callback) {
if (!this.events[event]) {
this.events[event] = []
}
this.events[event].push(callback)
},
publish (event, data) {
if (!this.events[event]) {
this.events[event] = []
}
this.events[event].forEach(callback => callback(data))
}
}
组件A:
<template>
<div>
<button @click="handleClick">向组件B传递数据</button>
</div>
</template>
<script>
import { PubSub } from './PubSub'
export default {
methods: {
handleClick () {
PubSub.publish('event', '组件A传递的数据')
}
}
}
</script>
组件B:
<template>
<div>
组件B接收到的数据:{{ data }}
</div>
</template>
<script>
import { PubSub } from './PubSub'
export default {
data () {
return {
data: ''
}
},
mounted () {
PubSub.subscribe('event', data => {
this.data = data
})
}
}
</script>
WebSocket (高级)
使用WebSocket协议实现实时通信,将所有组件连接到同一个WebSocket服务器,通过推送消息实现通信。
连接WebSocket服务器:
const ws = new WebSocket('ws://localhost:3000')
ws.onopen = function () {
console.log('WebSocket已连接')
}
ws.onclose = function () {
console.log('WebSocket已关闭')
}
ws.onerror = function () {
console.log('WebSocket出错')
}
组件A:
<template>
<div>
<button @click="handleClick">向组件B传递数据</button>
</div>
</template>
<script>
const ws = new WebSocket('ws://localhost:3000')
export default {
methods: {
handleClick () {
ws.send('组件A传递的数据')
}
}
}
</script>
组件B:
<template>
<div>
组件B接收到的数据:{{ data }}
</div>
</template>
<script>
const ws = new WebSocket('ws://localhost:3000')
export default {
data () {
return {
data: ''
}
},
mounted () {
ws.onmessage = event => {
this.data = event.data
}
}
}
</script>
路由参数(高级)
使用路由参数来传递数据,通常适用于父子组件之间或兄弟组件之间的通信。
父组件:
<template>
<div>
点击以下链接可以传递数据:<br>
<router-link :to="{ name: 'child', params: { data: '父组件传递的数据' } }">传递数据到子组件</router-link>
</div>
</template>
子组件:
<template>
<div>
子组件接收到的数据:{{ $route.params.data }}
</div>
</template>
<script>
export default {
mounted () {
console.log('子组件接收到的数据:' + this.$route.params.data)
}
}
</script>
兄弟组件:
<template>
<div>
兄弟组件接收到的数据:{{ $route.params.data }}
</div>
</template>
<script>
export default {
mounted () {
console.log('兄弟组件接收到的数据:' + this.$route.params.data)
}
}
</script>
Vuex状态管理(高级)
使用Vuex管理公共状态,组件通过Vuex进行通信。
store.js:
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
data: '共享的数据'
},
mutations: {
setData (state, data) {
state.data = data
}
}
})
组件A:
<template>
<div>
<button @click="handleClick">向组件B传递数据</button>
</div>
</template>
<script>
import store from './store'
export default {
methods: {
handleClick () {
store.commit('setData', '组件A传递的数据')
}
}
}
</script>
组件B:
<template>
<div>
组件B接收到的数据:{{ data }}
</div>
</template>
<script>
import { mapState } from 'vuex'
export default {
computed: {
...mapState(['data'])
},
mounted () {
console.log('组件B接收到的数据:' + this.data)
}
}
</script>
事件总线(高级)
使用一个空的Vue实例作为事件总线,组件A通过事件总线向组件B传递数据。
事件总线:
// EventBus.js
import Vue from 'vue'
export const EventBus = new Vue()
组件A:
<template>
<div>
<button @click="handleClick">向组件B传递数据</button>
</div>
</template>
<script>
import { EventBus } from './EventBus'
export default {
methods: {
handleClick () {
EventBus.$emit('event', '组件A传递的数据')
}
}
}
</script>
组件B:
<template>
<div>
组件B接收到的数据:{{ data }}
</div>
</template>
<script>
import { EventBus } from './EventBus'
export default {
data () {
return {
data: ''
}
},
mounted () {
EventBus.$on('event', data => {
this.data = data
})
}
}
</script>
三、往期优质推荐
VSCode 最全实用插件(VIP典藏版) |
Vue超详细整理(VIP典藏版) |
Vue中created,mounted,updated详解 |
一文快速上手Echarts(持续更新) |
Vue中el-table数据项扩展各种类型总结(持续更新) |
有用请点赞,养成良好习惯!
疑问、交流、鼓励请留言!