20 communication methods of Vue parent component and child component (the most complete summary of the whole network)

Table of contents

1. Commonly used

Props

parent component:

Subassembly:

$emit and $on

parent component:

Subassembly:

$parent and $children

parent component:

Subassembly:

$attrs and $listeners

parent component:

Subassembly:

provide and inject

parent component:

Subassembly:

2. Other explorations

EventBus

parent component:

Subassembly:

Vuex

store.js:

parent component:

Subassembly:

$refs property

parent component:

Subassembly:

$parent property

parent component:

Subassembly:

$root property

root component:

Subassembly:

provide / inject (advanced)

Ancestor component:

Direct child components:

Indirect subcomponents:

provide / inject + Vuex (advanced)

root component:

Subcomponents and grandchildren:

custom event

parent component:

Subassembly:

Communication between sibling components

EventBus.js:

Component A:

Component B:

localStorage (browser cache)

Component A:

Component B:

Publish Subscribe (Pub/Sub) mode

Message Center:

Component A:

Component B:

WebSocket (Advanced)

Connect to the WebSocket server:

Component A:

Component B:

Route Parameters (Advanced)

parent component:

Subassembly:

Sibling components:

Vuex state management (advanced)

store.js:

Component A:

Component B:

Event Bus (Advanced)

Event bus:

Component A:

Component B:

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

The most complete and practical plug-in for VSCode (VIP Collection Edition)
Vue Super Detailed Finishing (VIP Collection Edition)
Detailed explanation of created, mounted and updated in Vue
One article to quickly get started with Echarts (continuously updated)
Summary of various types of el-table data item extensions in Vue (continuously updated)

Please like it if it is useful, and develop a good habit!

Please leave a message for questions, exchanges, and encouragement!

Guess you like

Origin blog.csdn.net/libusi001/article/details/131668644