Table of contents
provide / inject + Vuex (advanced)
Subcomponents and grandchildren:
Communication between sibling components
Publish Subscribe (Pub/Sub) mode
Connect to the WebSocket server:
Vuex state management (advanced)
3. High-quality recommendations in the past
1. Commonly used
- Recently, I have been packaging various components to improve the development efficiency of team members.
- Encountered parent-child components in various situations, various value transfers between sibling components,
- Here is a summary and some exploration, welcome to add ~
Props
The parent component passes data to the child component, and the child component receives the data through the props attribute
parent component:
<template>
<div>
<child-component :parentData="data"></child-component>
</div>
</template>
<script>
import ChildComponent from './ChildComponent.vue'
export default {
components: {
ChildComponent
},
data () {
return {
data: '父组件传递的数据'
}
}
}
</script>
Subassembly:
<template>
<div>
子组件接收到的数据:{
{ parentData }}
</div>
</template>
<script>
export default {
props: {
parentData: String
}
}
</script>
What are the default value types of Vue props
$emit and $on
The child component transmits data to the parent component, the child component triggers an event through $emit, and the parent component listens to the event and receives data through $on.
parent component:
<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>
Subassembly:
<template>
<div>
<button @click="handleClick">点击触发事件</button>
</div>
</template>
<script>
export default {
methods: {
handleClick () {
this.$emit('childEvent', '子组件传递的数据')
}
}
}
</script>
$parent and $children
The parent component passes data to the child component, and the parent component obtains the child component instance through $children and calls the child component method to pass the data.
parent component:
<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>
Subassembly:
<template>
<div>
子组件
</div>
</template>
<script>
export default {
methods: {
handleData (data) {
console.log('子组件接收到的数据:' + data)
}
}
}
</script>
$attrs and $listeners
The parent component passes attributes and events to the child component, and the child component gets the attribute through $attrs, and gets the event through $listeners and binds it to the child component.
parent component:
<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>
Subassembly:
<template>
<div>
子组件
</div>
</template>
<script>
export default {
mounted () {
this.$emit('event1', '子组件传递的数据')
}
}
</script>
provide and inject
The parent component passes data to the child component, the parent component provides data through provide, and the child component injects data through inject.
parent component:
<template>
<div>
<child-component></child-component>
</div>
</template>
<script>
import ChildComponent from './ChildComponent.vue'
export default {
components: {
ChildComponent
},
provide () {
return {
parentData: '父组件提供的数据'
}
}
}
</script>
Subassembly:
<template>
<div>
子组件接收到的数据:{
{ childData }}
</div>
</template>
<script>
export default {
inject: ['parentData'],
computed: {
childData () {
return this.parentData + ',子组件加工处理后的数据'
}
}
}
</script>
2. Other explorations
EventBus
Communication between parent components and child components is carried out through a central event bus (EventBus).
EventBus.js:
import Vue from 'vue'
export const EventBus = new Vue()
parent component:
<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>
Subassembly:
<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
The parent component and the child component communicate through Vuex, sharing the same state tree.
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
}
}
})
parent component:
<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>
Subassembly:
<template>
<div>
子组件接收到的数据:{
{ childData }}
</div>
</template>
<script>
import { mapState } from 'vuex'
export default {
computed: {
...mapState(['data']),
childData () {
return this.data + ',子组件加工处理后的数据'
}
}
}
</script>
$refs property
The parent component can obtain the instance of the child component through $refs, and then access the properties and methods of the child component.
parent component:
<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>
Subassembly:
<template>
<div>
子组件接收到的数据:{
{ childData }}
</div>
</template>
<script>
export default {
data () {
return {
childData: '子组件原始数据'
}
}
}
</script>
$parent property
Child components can obtain the instance of the parent component through $parent, and then access the properties and methods of the parent component.
parent component:
<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>
Subassembly:
<template>
<div>
<button @click="handleChild">调用父组件方法</button>
</div>
</template>
<script>
export default {
methods: {
handleChild () {
console.log(this.$parent.parentData)
this.$parent.handleParent()
}
}
}
</script>
$root property
Subcomponents can obtain the instance of the root component through $root, and then access the properties and methods of the root component.
root component:
<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>
Subassembly:
<template>
<div>
子组件
</div>
</template>
<script>
export default {
mounted () {
console.log('根组件的数据:' + this.$root.rootData)
this.$root.rootMethod()
}
}
</script>
provide / inject (advanced)
provide / inject allows ancestor components to inject a dependency to all descendant components, allowing these components to use the same dependency injection.
Ancestor component:
<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>
Direct child components:
<template>
<div>
子组件
</div>
</template>
<script>
export default {
inject: ['sharedObj']
}
</script>
Indirect subcomponents:
<template>
<div>
子组件接收到的数据:{
{ childData }}
</div>
</template>
<script>
export default {
inject: ['sharedObj'],
computed: {
childData () {
return this.sharedObj.message + ',子组件加工处理后的数据'
}
}
}
</script>
provide / inject + Vuex (advanced)
Use provide/inject to inject an instance of Vuex so that all components use the same Vuex instance.
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
}
}
})
root component:
<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>
Subcomponents and grandchildren:
<template>
<div>
组件接收到的数据:{
{ componentData }}
</div>
</template>
<script>
export default {
inject: {
store: {
default: null
}
},
computed: {
componentData () {
return this.store.state.data + ',组件加工处理后的数据'
}
}
}
</script>
custom event
Use vm.$on(eventName, callback)
event listeners, use vm.$emit(eventName, ...args)
trigger events.
parent component:
<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>
Subassembly:
<template>
<div>
<button @click="handleClick">点击触发事件</button>
</div>
</template>
<script>
export default {
methods: {
handleClick () {
this.$emit('custom-event', '子组件传递的数据')
}
}
}
</script>
Communication between sibling components
Use an empty Vue instance as an event bus, send events to the event bus on the one hand, and listen to events on the other.
EventBus.js:
import Vue from 'vue'
export const EventBus = new Vue()
Component A:
<template>
<div>
<button @click="handleClick">向组件B传递数据</button>
</div>
</template>
<script>
import { EventBus } from './EventBus'
export default {
methods: {
handleClick () {
EventBus.$emit('event', '组件A传递的数据')
}
}
}
</script>
Component 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 (browser cache)
Use the browser cache to store data, store and listen to the data in the cache in components that need to communicate.
Component A:
<template>
<div>
<button @click="handleClick">向组件B传递数据</button>
</div>
</template>
<script>
export default {
methods: {
handleClick () {
localStorage.setItem('data', '组件A传递的数据')
}
}
}
</script>
Component 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>
Publish Subscribe (Pub/Sub) mode
Using a message center, subscribers subscribe messages to the message center, publishers publish messages to the message center, and the message center notifies all subscribers of the message.
Message Center:
// 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))
}
}
Component A:
<template>
<div>
<button @click="handleClick">向组件B传递数据</button>
</div>
</template>
<script>
import { PubSub } from './PubSub'
export default {
methods: {
handleClick () {
PubSub.publish('event', '组件A传递的数据')
}
}
}
</script>
Component 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 (Advanced)
Use the WebSocket protocol to realize real-time communication, connect all components to the same WebSocket server, and realize communication by pushing messages.
Connect to the WebSocket server:
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出错')
}
Component 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>
Component 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>
Route Parameters (Advanced)
Using routing parameters to pass data is usually suitable for communication between parent and child components or between sibling components.
parent component:
<template>
<div>
点击以下链接可以传递数据:<br>
<router-link :to="{ name: 'child', params: { data: '父组件传递的数据' } }">传递数据到子组件</router-link>
</div>
</template>
Subassembly:
<template>
<div>
子组件接收到的数据:{
{ $route.params.data }}
</div>
</template>
<script>
export default {
mounted () {
console.log('子组件接收到的数据:' + this.$route.params.data)
}
}
</script>
Sibling components:
<template>
<div>
兄弟组件接收到的数据:{
{ $route.params.data }}
</div>
</template>
<script>
export default {
mounted () {
console.log('兄弟组件接收到的数据:' + this.$route.params.data)
}
}
</script>
Vuex state management (advanced)
Use Vuex to manage public state, and components communicate through 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
}
}
})
Component A:
<template>
<div>
<button @click="handleClick">向组件B传递数据</button>
</div>
</template>
<script>
import store from './store'
export default {
methods: {
handleClick () {
store.commit('setData', '组件A传递的数据')
}
}
}
</script>
Component B:
<template>
<div>
组件B接收到的数据:{
{ data }}
</div>
</template>
<script>
import { mapState } from 'vuex'
export default {
computed: {
...mapState(['data'])
},
mounted () {
console.log('组件B接收到的数据:' + this.data)
}
}
</script>
Event Bus (Advanced)
Using an empty Vue instance as the event bus, component A passes data to component B through the event bus.
Event bus:
// EventBus.js
import Vue from 'vue'
export const EventBus = new Vue()
Component A:
<template>
<div>
<button @click="handleClick">向组件B传递数据</button>
</div>
</template>
<script>
import { EventBus } from './EventBus'
export default {
methods: {
handleClick () {
EventBus.$emit('event', '组件A传递的数据')
}
}
}
</script>
Component 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>
3. High-quality recommendations in the past
Please like it if it is useful, and develop a good habit!
Please leave a message for questions, exchanges, and encouragement!