Есть так много способов общаться с компонентами Vue? Сколько ты знаешь

Vue.js
Есть так много способов общаться с компонентами Vue? Сколько ты знаешь

Очень часто на собеседованиях задают вопрос о способе коммуникации компонентов vue. Я часто сталкивался с этой проблемой, когда только начинал искать стажировку. Тогда я знал только, как вернуться к props и $emit. Позже, с углублением обучения, я открыл для себя vue. Существует так много способов взаимодействия между компонентами!
Сегодня я подытожу методы коммуникации компонентов vue.Если есть какие-то упущения в написании, пожалуйста, не стесняйтесь, дайте мне знать.

1. props/$emit

Введение

Я полагаю, вы хорошо знакомы с props и $emit, которые являются наиболее часто используемыми методами коммуникации Vue.
реквизит:props могут быть массивами или объектами и используются для получения данных, передаваемых через v-bind от родительских компонентов. Когда реквизит является массивом, он напрямую получает свойства, переданные родительским компонентом; когда реквизит является объектом, вы можете установить тип, значение по умолчанию, обязательную передачу и правила проверки свойства с помощью конфигурации, такой как тип, значение по умолчанию, обязательный и валидатор.
$ излучать:Когда взаимодействует родительско-дочерний компонент, мы обычно используем $emit для запуска родительского компонента v-on для привязки соответствующего прослушивателя событий к дочернему компоненту.

Примеры кода

Следующий код используется для реализации связи между родительским и дочерним компонентами props и $emit, В этом примере мы реализовали следующую связь:

  • Передача значений от родителя к дочернему: родительский компонент передает:messageFromParent="message"Передайте значение сообщения родительского компонента дочернему компоненту.При вводе входного тега родительского компонента содержимое тега p дочернего компонента изменится соответствующим образом.
  • Дочерний элемент передает значение родителю: родительский компонент передает@on-receive="receive"Слушатель события получения привязан к подкомпоненту.При вводе входного тега подкомпонента будет запущена функция обратного вызова получения.this.$emit('on-receive', this.message)Присвойте значение сообщения дочернего компонента родительскому компоненту messageFromChild, чтобы изменить содержимое тега p родительского компонента.

Пожалуйста, смотрите код:

// 子组件代码
<template>
  <div class="child">
    <h4>this is child component</h4>
    <input type="text" v-model="message" @keyup="send" />
    <p>收到来自父组件的消息:{{ messageFromParent }}</p>
  </div>
</template>
<script>
export default {
  name: 'Child',
  props: ['messageFromParent'],  // 通过props接收父组件传过来的消息
  data() {
    return {
      message: '',
    }
  },
  methods: {
    send() {
      this.$emit('on-receive', this.message)  // 通过$emit触发on-receive事件,调用父组件中receive回调,并将this.message作为参数
    },
  },
}
</script>
// 父组件代码
<template>
  <div class="parent">
    <h3>this is parent component</h3>
    <input type="text" v-model="message" />
    <p>收到来自子组件的消息:{{ messageFromChild }}</p>
    <Child :messageFromParent="message" @on-receive="receive" />
  </div>
</template>
<script>
import Child from './child'
export default {
  name: 'Parent',
  data() {
    return {
      message: '', // 传递给子组件的消息
      messageFromChild: '',
    }
  },
  components: {
    Child,
  },
  methods: {
    receive(msg) { // 接受子组件的信息,并将其赋值给messageFromChild
      this.messageFromChild = msg
    },
  },
}
</script>

Предварительный просмотр эффекта

2. v-slot

Введение

v-slot — это новый API для унифицированной реализации слотов и именованных слотов в Vue2.6, который используется для заменыslot(2.6.0废弃),slot-scope(2.6.0废弃),scope(2.5.0废弃)и т. д. апи.
v-slot используется в теге шаблона для предоставления именованных слотов или слотов, которые должны получать реквизиты.Если v-slot не указан, используется значение по умолчанию по умолчанию.

пример кода

См. пример кода v-slot ниже, в этом примере мы реализовали:

  • Передача значений от родителя к дочернему: родительский компонент передает<template v-slot:child>{{ message }}</template>Передайте значение сообщения родительского компонента дочернему компоненту, а дочерний компонент передает<slot name="child"></slot>Принимается соответствующий контент и осуществляется передача значения от родителя к дочернему элементу.
// 子组件代码
<template>
  <div class="child">
    <h4>this is child component</h4>
    <p>收到来自父组件的消息:
      <slot name="child"></slot>  <!--展示父组件通过插槽传递的{{message}}-->
    </p>
  </div>
</template>
<template>
  <div class="parent">
    <h3>this is parent component</h3>
    <input type="text" v-model="message" />
    <Child>
      <template v-slot:child>
        {{ message }}  <!--插槽要展示的内容-->
      </template>
    </Child>
  </div>
</template>
<script>
import Child from './child'
export default {
  name: 'Parent',
  data() {
    return {
      message: '',
    }
  },
  components: {
    Child,
  },
}
</script>

Предварительный просмотр эффекта

3. $refs/$parent/$children/$root

Введение

Мы также можем пройти$refs/$parent/$children/$rootПолучите экземпляр компонента Vue другими способами и получите свойства и методы, привязанные к экземпляру, чтобы реализовать связь между компонентами.
$ссылки:Обычно мы привязываем $refs к элементам DOM, чтобы получить атрибуты элементов DOM. При реализации взаимодействия компонентов мы также можем привязать $refs к подкомпонентам, чтобы получить экземпляры подкомпонентов.
$ родитель:Мы можем сделать это прямо в Vue черезthis.$parentЧтобы получить текущий родительский компонент экземпляра компонента (если есть).
$ Дети:Точно так же мы можем передать его прямо в Vue.this.$childrenчтобы получить массив экземпляров дочерних компонентов текущего компонента. Но следует отметить, что,this.$childrenНижние индексы элементов в массиве не обязательно соответствуют порядку дочерних компонентов, на которые ссылается родительский компонент, например дочерний компонент, который загружается асинхронно, что может повлиять на его порядок в дочернем массиве. Поэтому при его использовании нужно найти соответствующий подкомпонент по определенным условиям, например, по названию подкомпонента.
$корень:Получите корневой экземпляр Vue текущего дерева компонентов. Если у текущего экземпляра нет родителя, этот экземпляр будет самим собой. С помощью $root мы можем обеспечить межуровневую связь между компонентами.

пример кода

Давайте рассмотрим пример использования $parent и $children (поскольку использование этих API похоже, поэтому использование $refs и $root здесь не будет расширяться, а будет реализовано в этом примере:

  • Передача значений от родителя к дочернему: дочерние компоненты проходят$parent.messageПолучите значение сообщения в родительском компоненте.
  • Дочерний элемент передает значение родителю: родительский компонент передает$childrenПолучите массив экземпляров дочерних компонентов, пройдитесь по массиву, получите соответствующий экземпляр дочернего компонента Child1 по имени экземпляра, назначьте его дочернему элементу1, а затем передайтеchild1.messageПолучите сообщение дочернему компоненту Child1.

код показывает, как показано ниже:

// 子组件
<template>
  <div class="child">
    <h4>this is child component</h4>
    <input type="text" v-model="message" />
    <p>收到来自父组件的消息:{{ $parent.message }}</p>  <!--展示父组件实例的message-->
  </div>
</template>
<script>
export default {
  name: 'Child1',
  data() {
    return {
      message: '',   // 父组件通过this.$children可以获取子组件实例的message
    }
  },
}
</script>
// 父组件
<template>
  <div class="parent">
    <h3>this is parent component</h3>
    <input type="text" v-model="message" />
    <p>收到来自子组件的消息:{{ child1.message }}</p> <!--展示子组件实例的message-->
    <Child />
  </div>
</template>
<script>
import Child from './child'
export default {
  name: 'Parent',
  data() {
    return {
      message: '',
      child1: {},
    }
  },
  components: {
    Child,
  },
  mounted() {
    this.child1 = this.$children.find((child) => {
      return child.$options.name === 'Child1'  // 通过options.name获取对应name的child实例
    })
  },
}
</script>

Предварительный просмотр эффекта

4. $attrs/$listener

Введение

И $attrs, и $listeners — это недавно добавленные атрибуты в Vue2.4, которые в основном используются пользователями для разработки расширенных компонентов.

$ атрибуты:Используется для получения свойств атрибутов, которые не распознаются как свойства в родительской области и могут быть переданы черезv-bind="$attrs"Передача внутренних компонентов — полезно при создании высокоуровневых компонентов.
Представьте, что при создании компонента вам нужно получить десятки параметров, таких как param1, param2, param3 и т.д. Если вы передаете props, то вам нужно передатьprops: ['param1', 'param2', 'param3', ……]Куча других деклараций. Будет сложнее, если некоторые из этих реквизитов нужно будет передать более глубоким подкомпонентам.
А с $attrs вам не нужны никакие объявления, просто передайте$attrs.param1,$attrs.param2... можно использовать, и приведенный выше пример также очень удобен для перехода к глубоким подкомпонентам.

$слушатели:Содержит прослушиватель событий v-on в родительской области. это может пройтиv-on="$listeners"Передача внутренних компонентов — полезно при создании компонентов более высокого уровня, это используется так же, как $ attrs при передаче.

пример кода

В этом примере есть три компонента: A, B, C, и связь такова: [ A [ B [C] ] ], A является родительским компонентом B, а B является родительским компонентом C. То есть: компонент A уровня 1, компонент B уровня 2 и компонент C уровня 3. Мы достигли:

  • Передача значений от родителя к дочернему: компонент A уровня 1 проходит:messageFromA="message"Передайте свойство сообщения компоненту B уровня 2, который передает компонент B уровня 2.$attrs.messageFromAПолучите сообщение компонента А уровня 1.
  • Передача значений по уровням: компонент A уровня 1 проходит:messageFromA="message"Передайте свойство сообщения компоненту B уровня 2, а компонент B уровня 2 затем передаст v-bind="$attrs"Передайте его на уровень 3, компонент C, уровень 3, компонент C проходит$attrs.messageFromAПолучите сообщение компонента А уровня 1.
  • Ребенок передает значение родителю: компонент А уровня 1 передает@keyup="receive"Привяжите прослушиватель события keyup к компоненту-потомку, а компонент второго уровня B передаетv-on="$listeners"для привязки события keyup к его входному тегу. Когда вводится поле ввода компонента B второго уровня, будет запущен обратный вызов приема компонента A первого уровня, а значение в поле ввода ввода компонента B второго уровня будет присвоено messageFromComp. компонента A первого уровня, чтобы реализовать передачу значения от дочернего к родительскому.
  • Значение межуровневой загрузки: компонент A уровня 1 пройден@keyup="receive"Привяжите прослушиватель события keyup к компоненту-потомку, а компонент второго уровня B передает <CompC v-on="$listeners" />Передайте это С. Компонент С уровня 3 пройденv-on="$listeners"для привязки события keyup к его входному тегу. Когда вводится поле ввода компонента третьего уровня C, будет запущен обратный вызов приема компонента A первого уровня, и значение в поле ввода компонента третьего уровня C будет присвоено messageFromComp of компонента A первого уровня, тем самым реализуя значение загрузки между уровнями.

код показывает, как показано ниже:

// 3级组件C
<template>
  <div class="compc">
    <h5>this is C component</h5>
    <input name="compC" type="text" v-model="message" v-on="$listeners" /> <!--将A组件keyup的监听回调绑在该input上-->
    <p>收到来自A组件的消息:{{ $attrs.messageFromA }}</p>
  </div>
</template>
<script>
export default {
  name: 'Compc',
  data() {
    return {
      message: '',
    }
  },
}
</script>
// 2级组件B
<template>
  <div class="compb">
    <h4>this is B component</h4>
    <input name="compB" type="text" v-model="message" v-on="$listeners" />  <!--将A组件keyup的监听回调绑在该input上-->
    <p>收到来自A组件的消息:{{ $attrs.messageFromA }}</p>
    <CompC v-bind="$attrs" v-on="$listeners" /> <!--将A组件keyup的监听回调继续传递给C组件,将A组件传递的attrs继续传递给C组件-->
  </div>
</template>
<script>
import CompC from './compC'
export default {
  name: 'CompB',
  components: {
    CompC,
  },
  data() {
    return {
      message: '',
    }
  },
}
</script>
// A组件
<template>
  <div class="compa">
    <h3>this is A component</h3>
    <input type="text" v-model="message" />
    <p>收到来自{{ comp }}的消息:{{ messageFromComp }}</p>
    <CompB :messageFromA="message" @keyup="receive" />  <!--监听子孙组件的keyup事件,将message传递给子孙组件-->
  </div>
</template>
<script>
import CompB from './compB'
export default {
  name: 'CompA',
  data() {
    return {
      message: '',
      messageFromComp: '',
      comp: '',
    }
  },
  components: {
    CompB,
  },
  methods: {
    receive(e) { // 监听子孙组件keyup事件的回调,并将keyup所在input输入框的值赋值给messageFromComp
      this.comp = e.target.name
      this.messageFromComp = e.target.value
    },
  },
}
</script>

Предварительный просмотр эффекта

5. provide/inject

Введение

Пара опций «предоставить/внедрить» должна использоваться вместе, чтобы позволить компоненту-предку внедрить зависимость всем своим потомкам, независимо от того, насколько глубока иерархия компонентов, и это всегда будет действовать до тех пор, пока его восходящие и нисходящие отношения учредил. Если вы одноклассник, знакомый с React, вы сразу подумаете о Context API — они очень похожи.
предоставлять:является объектом или функцией, которая возвращает объект. Этот объект содержит свойства, которые могут быть внедрены в его потомков, т.е. свойства и значения свойств, которые будут переданы потомкам.
ввод:Массив строк или объект. Когда это строковый массив, использование очень похоже на свойства, за исключением того, что полученные свойства изменяются с данных на свойства в условии. Когда это объект, похожий на props, вы можете установить значения по умолчанию, настроив такие свойства, как default и from, использовать новые именованные свойства в дочерних компонентах и ​​так далее.

пример кода

В этом примере есть три компонента: компонент 1-го уровня A, компонент 2-го уровня B, компонент 3-го уровня C: [A[B[C]]], A — родительский компонент B, а B — родительский компонент. С. Реализовано в примере:

  • Передача значений от родителя к дочернему: компонент A уровня 1 вводит сообщение в компоненты-потомки через предоставление, компонент B уровня 2 передаетinject: ['messageFromA']чтобы получить сообщение от компонента A уровня 1 и передатьmessageFromA.contentПолучите значение атрибута содержимого сообщения в компоненте первого уровня A.
  • Передача значений по уровням: компонент A уровня 1 вводит сообщение в компоненты-потомки через предоставление, а компонент C уровня 3 передаетinject: ['messageFromA']чтобы получить сообщение от компонента A уровня 1 и передатьmessageFromA.contentПолучите значение атрибута содержимого сообщения в компоненте A первого уровня и передайте значение вниз по уровню.

код показывает, как показано ниже:

// 1级组件A
<template>
  <div class="compa">
    <h3>this is A component</h3>
    <input type="text" v-model="message.content" />
    <CompB />
  </div>
</template>
<script>
import CompB from './compB'
export default {
  name: 'CompA',
  provide() {
    return {
      messageFromA: this.message,  // 将message通过provide传递给子孙组件
    }
  },
  data() {
    return {
      message: {
        content: '',
      },
    }
  },
  components: {
    CompB,
  },
}
</script>
// 2级组件B
<template>
  <div class="compb">
    <h4>this is B component</h4>
    <p>收到来自A组件的消息:{{ messageFromA && messageFromA.content }}</p>
    <CompC />
  </div>
</template>
<script>
import CompC from './compC'
export default {
  name: 'CompB',
  inject: ['messageFromA'], // 通过inject接受A中provide传递过来的message
  components: {
    CompC,
  },
}
</script>
// 3级组件C
<template>
  <div class="compc">
    <h5>this is C component</h5>
    <p>收到来自A组件的消息:{{ messageFromA && messageFromA.content }}</p>
  </div>
</template>
<script>
export default {
  name: 'Compc',
  inject: ['messageFromA'], // 通过inject接受A中provide传递过来的message
}
</script>

будь осторожен:

  1. Некоторые студенты могут спросить меня, почему сообщение в компоненте первого уровня A выше использует тип объекта вместо типа строки, потому что привязка vue provider и inject не отвечает. Если сообщение строкового типа, оно не может быть назначено messageFromA после изменения значения сообщения через поле ввода в компоненте A уровня 1. Если оно имеет тип объекта, при изменении значения атрибута объекта значение атрибута в messageFromA все еще может соответственно измениться.Значения свойств объекта, полученные инъекцией компонента-потомка, также могут измениться соответствующим образом.
  2. Потомки предоставляют те же свойства, что и предки, и переопределяют значение предоставления предка в потомках. Например, компонент B второго уровня также вводит значение messageFromA в компонент C третьего уровня посредством предоставления, тогда messageFromA в компоненте C третьего уровня предпочтительно получит значение, введенное компонентом B второго уровня, а не Компонент первого уровня А.

Предварительный просмотр эффекта

6. eventBus

Введение

EventBus, также известная как шина событий, регистрирует новый экземпляр Vue, прослушивает и инициирует события этого экземпляра, вызывая $emit и $on этого экземпляра, и реализует глобальную связь компонентов, передавая параметры. Это компонент, у которого нет DOM, только его методы экземпляра, поэтому он очень легкий.
Мы можем сделать это, зарегистрировавшись в глобальном экземпляре Vue:

// main.js
Vue.prototype.$Bus = new Vue()

Но когда проект слишком велик, нам лучше абстрагировать шину событий в один файл и импортировать ее в каждый файл компонента, который необходимо использовать. Таким образом, он не загрязняет глобальное пространство имен:

// bus.js,使用时通过import引入
import Vue from 'vue'
export const Bus = new Vue()

Принципиальный анализ

Принцип eventBus на самом деле относительно прост, то есть используется режим публикации подписки для реализации двух методов $emit и $on:

// eventBus原理
export default class Bus {
  constructor() {
    this.callbacks = {}
  }
  $on(event, fn) {
    this.callbacks[event] = this.callbacks[event] || []
    this.callbacks[event].push(fn)
  }
  $emit(event, args) {
    this.callbacks[event].forEach((fn) => {
      fn(args)
    })
  }
}

// 在main.js中引入以下
// Vue.prototype.$bus = new Bus()

пример кода

В этом примере всего включены 4 компонента: [A[B[C,D]]], компонент A уровня 1, компонент B уровня 2, компонент C уровня 3 и компонент D уровня 3. Мы достигаем этого с помощью eventBus:

  • Глобальная связь: включает связь между родительскими и дочерними компонентами, связь между одноуровневыми компонентами и связь между межуровневыми компонентами. Логика работы четырех компонентов одинакова.this.$bus.$emit('sendMessage', obj)Запустите обратный вызов события sendMessage, инкапсулируйте отправителя и сообщение как объекты и передайте их в качестве параметров;this.$bus.$on('sendMessage', obj)Слушайте событие sendMessage других компонентов и копируйте значение текущего отправителя примера компонента и сообщения. Таким образом, когда значение поля ввода любого компонента изменяется, другие компоненты могут получать соответствующую информацию для осуществления глобальной связи.

код показывает, как показано ниже:

// main.js
Vue.prototype.$bus = new Vue()
// 1级组件A
<template>
  <div class="containerA">
    <h2>this is CompA</h2>
    <input type="text" v-model="message" @keyup="sendMessage" />
    <p v-show="messageFromBus && sender !== $options.name">
      收到{{ sender }}的消息:{{ messageFromBus }}
    </p>
    <CompB />
  </div>
</template>
<script>
import CompB from './compB'
export default {
  name: 'CompA',
  components: {
    CompB,
  },
  data() {
    return {
      message: '',
      messageFromBus: '',
      sender: '',
    }
  },
  mounted() {
    this.$bus.$on('sendMessage', (obj) => {  // 通过eventBus监听sendMessage事件
      const { sender, message } = obj
      this.sender = sender
      this.messageFromBus = message
    })
  },
  methods: {
    sendMessage() {
      this.$bus.$emit('sendMessage', { // 通过eventBus触发sendMessage事件
        sender: this.$options.name,
        message: this.message,
      })
    },
  },
}
</script>
// 2级组件B
<template>
  <div class="containerB">
    <h3>this is CompB</h3>
    <input type="text" v-model="message" @keyup="sendMessage" />
    <p v-show="messageFromBus && sender !== $options.name">
      收到{{ sender }}的消息:{{ messageFromBus }}
    </p>
    <CompC />
    <CompD />
  </div>
</template>
<script>
import CompC from './compC'
import CompD from './compD'
export default {
  name: 'CompB',
  components: {
    CompC,
    CompD,
  },
  data() {
    return {
      message: '',
      messageFromBus: '',
      sender: '',
    }
  },
  mounted() {
    this.$bus.$on('sendMessage', (obj) => { // 通过eventBus监听sendMessage事件
      const { sender, message } = obj
      this.sender = sender
      this.messageFromBus = message
    })
  },
  methods: {
    sendMessage() {
      this.$bus.$emit('sendMessage', { // 通过eventBus触发sendMessage事件
        sender: this.$options.name,
        message: this.message,
      })
    },
  },
}
</script>
// 3级组件C
<template>
  <div class="containerC">
    <p>this is CompC</p>
    <input type="text" v-model="message" @keyup="sendMessage" />
    <p v-show="messageFromBus && sender !== $options.name">
      收到{{ sender }}的消息:{{ messageFromBus }}
    </p>
  </div>
</template>
<script>
export default {
  name: 'CompC',
  data() {
    return {
      message: '',
      messageFromBus: '',
      sender: '',
    }
  },
  mounted() {
    this.$bus.$on('sendMessage', (obj) => { // 通过eventBus监听sendMessage事件
      const { sender, message } = obj
      this.sender = sender
      this.messageFromBus = message
    })
  },
  methods: {
    sendMessage() {
      this.$bus.$emit('sendMessage', { // 通过eventBus触发sendMessage事件
        sender: this.$options.name,
        message: this.message,
      })
    },
  },
}
</script>
// 3级组件D
<template>
  <div class="containerD">
    <p>this is CompD</p>
    <input type="text" v-model="message" @keyup="sendMessage" />
    <p v-show="messageFromBus && sender !== $options.name">
      收到{{ sender }}的消息:{{ messageFromBus }}
    </p>
  </div>
</template>
<script>
export default {
  name: 'CompD',
  data() {
    return {
      message: '',
      messageFromBus: '',
      sender: '',
    }
  },
  mounted() {
    this.$bus.$on('sendMessage', (obj) => { // 通过eventBus监听sendMessage事件
      const { sender, message } = obj
      this.sender = sender
      this.messageFromBus = message
    })
  },
  methods: {
    sendMessage() {
      this.$bus.$emit('sendMessage', { // 通过eventBus触发sendMessage事件
        sender: this.$options.name,
        message: this.message,
      })
    },
  },
}
</script>

Предварительный просмотр эффекта

7. Vuex

Когда проект огромен, когда несколько человек поддерживают один и тот же проект, если шина событий используется для глобальной связи, легко сделать изменения глобальных переменных труднопредсказуемыми. Отсюда и рождение Vuex.
Vuex — это шаблон управления состоянием, разработанный для приложений Vue.js. Он использует централизованное хранилище для управления состоянием всех компонентов приложения и использует соответствующие правила, чтобы гарантировать предсказуемое изменение состояния.
Для содержимого Vuex вы можете обратиться кОфициальная документация Vuex, я не буду тут возиться, просто посмотрите на код.

пример кода

Экземпляр Vuex и шина событий leisi также содержат 4 компонента: [ A [ B [ C, D ] ] ], одноуровневый компонент A, двухуровневый компонент B, трехуровневый компонент C и трехуровневый компонент D. Мы реализовали в этом экземпляре:

  • Глобальная коммуникация: содержание кода похоже на eventBus, но гораздо удобнее в использовании, чем eventBus. Каждый компонент прослушивает изменения в поле ввода с помощью часов и запускает мутации через значение ввода через фиксацию vuex, тем самым изменяя значение stroe. Затем каждый компонент динамически получает данные в хранилище посредством вычислений для достижения глобальной связи.
// store.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
  state: {
    message: {
      sender: '',
      content: '',
    },
  },
  mutations: {
    sendMessage(state, obj) {
      state.message = {
        sender: obj.sender,
        content: obj.content,
      }
    },
  },
})
// 组件A
<template>
  <div class="containerA">
    <h2>this is CompA</h2>
    <input type="text" v-model="message" />
    <p v-show="messageFromStore && sender !== $options.name">
      收到{{ sender }}的消息:{{ messageFromStore }}
    </p>
    <CompB />
  </div>
</template>
<script>
import CompB from './compB'
export default {
  name: 'CompA',
  components: {
    CompB,
  },
  data() {
    return {
      message: '',
    }
  },
  computed: {
    messageFromStore() {
      return this.$store.state.message.content
    },
    sender() {
      return this.$store.state.message.sender
    },
  },
  watch: {
    message(newValue) {
      this.$store.commit('sendMessage', {
        sender: this.$options.name,
        content: newValue,
      })
    },
  },
}
</script>

Тоже самое, что и в eventBus, код в компонентах B, C и D тот же за исключением введения подкомпонентов, и скриптовая часть такая же, так что дальше писать не будем.

Предварительный просмотр эффекта

Суммировать

Выше упомянуто в общей сложности 7 методов связи компонентов Vue, а типы связи, которые они могут выполнять, показаны на следующем рисунке:

  • props/$emit: может быть достигнута двусторонняя связь между родительскими и дочерними компонентами, что, как правило, является нашим наиболее распространенным выбором при ежедневном общении между родительскими и дочерними компонентами.
  • v-slot: может реализовать одностороннюю связь между родительским и дочерним компонентами (передача значений от родителя к дочернему), при реализации повторно используемых компонентов, передаче узлов DOM, html и другого контента компонентам и вторичной обработке табличных значений. в некоторых библиотеках компонентов и т. д. v-slot может иметь приоритет.
  • $refs/$parent/$children/$root: может быть реализована двусторонняя связь между родительским и дочерним компонентами, в которой $root может реализовать одностороннюю межуровневую передачу значений от экземпляра корневого компонента к дочерним компонентам. Если родительский компонент не передает значение или прослушивает привязку v-on, а родительский и дочерний компоненты хотят получить свойства или методы друг друга, вы можете рассмотреть возможность использования этих API.
  • $attrs/$listeners: он может реализовать двустороннюю связь между уровнями, позволяя вам легко получать входящие атрибуты и прослушиватели привязок, а также легко передавать их подкомпонентам, что очень полезно при создании расширенных компонентов.
  • обеспечить/внедрить: он может реализовать межуровневую одностороннюю связь и легко внедрить зависимости в компоненты-потомки.Это лучший выбор для вас, чтобы реализовать расширенные компоненты и создать библиотеки компонентов.
  • EventBus: может быть реализована глобальная связь.В случае небольшого масштаба проекта, eventBus может использоваться для реализации глобального мониторинга событий. Тем не менее, eventBus следует использовать с осторожностью, чтобы избежать глобального загрязнения и утечек памяти.
  • Vuex: глобальная коммуникация может быть достигнута, что является лучшей практикой для глобального управления состоянием проектов Vue. Когда проект относительно большой, и вы хотите централизованно управлять состоянием глобальных компонентов, правильно установить Vuex!

Наконец Лу Синь сказал: «Миску горячего и кислого супа, лучше глотнуть лично, чем слышать».
(Лу Синь: я действительно это сказал!)
Прочитав так много, лучше постучите по нему самостоятельно, чтобы лучше понять его.После прочтения вы можете нажать на него вручную, чтобы углубить свое понимание.