Сводка по взаимодействию компонента Vue3

Vue.js
Сводка по взаимодействию компонента Vue3

предисловие

Недавно я видел эту статью одного большого парня в нашем сообществе.Краткое изложение методов связи компонентов Vue и сценариев их применения, Чувствоvue2Способы общения и сценарии применения подытожены очень хорошо, так что я приветствую😄 большого парня. совсем недавно училсяvue3, так что тоже думаем о подведении итогов вvue3Способ взаимодействия компонентов коммуникации.

мы знаемvue3изComposition Apiявляется одним из его самых ярких моментов, поэтому все нижеперечисленное находится вsetupРеализация демонстрационного кода в . Позже мы разработаем несколько простыхform组件Продемонстрируйте, например.

Основная операция

Вот простая разработкаVInputкомпонент поля ввода. Компонент похож на функцию, в основном связанную с вводом и выводом.Vue3существуетsetupФункция предоставляет два параметра, одинprops,одинcontextпоследующийemitметоды обработки ввода и вывода соответственно.

props

СейчасVInputЭто дочерний компонент, мне нужно, чтобы он принимал значение, переданное родителем, чтобы он мог помочь мне выполнить последующую логическую обработку и вернуть его родителю. Поэтому здесь требуются некоторые основные методы общения отца и сына.v-bind,props.

в родительском компоненте

<template>
   // 通过v-bind将数据想子组件传递
  <VInput :value="valueRef" />
</template>

const valueRef = ref('')

VInput

<template>
  <input :value="value" type="text" />
</template>

<script lang="ts">
import { defineComponent } from 'vue'

export default defineComponent({
  name: 'VInput',
  props: {
    value: String
  },
  setup(props) {
    // 其他逻辑
    
    // 接受到这个值
    console.log(props.value)
    return {}
  }
})
</script>

emit

Когда мы принимаем параметры в компоненте и выполняем какую-то логическую обработку, нам нужно вернуть обработанное значение наружу, а снаружи нужно реализовать функцию события, чтобы принять его. В этот момент я могу использоватьemitметод

Предположим, мы хотимVInputКомпонент возвращает наружу строку ограниченной длины. В этот момент внешнему объекту необходимо реализовать соответствующую функцию события, чтобы получить это значение, а затемVInputВнутренняя связьemitВыполните событие и верните внутренне обработанное значение в качестве параметра.

VInput

<template>
  <input :value="value" type="text" @input="onInput" ref="inputRef" />
</template>

<script lang="ts">
import { defineComponent, ref } from 'vue'

export default defineComponent({
  name: 'VInput',
  props: {
    value: String,
    maxLength: Number
  },
  setup(props, { emit }) {
     // Vue3中获取组件或者dom实例的一种方式
    const inputRef = ref()
    
    // 限制文字长度
    const limitLength = (value: string, maxLength: number) =>
      value.slice(0, maxLength)
    
    
    // 输入控制
    const controlled = (value: string) => {
      inputRef.value.value = value
    }

    const onInput = (e: any) => {
      let value = e.target.value

      if (typeof props.maxLength === 'number' && props.maxLength >= 0) {
        value = limitLength(value, props.maxLength)
      }

      controlled(value)
      
      // 向外部返回一个处理过的值
      emit('onInput', value)
    }
    return {
      onInput,
      inputRef
    }
  }
})
</script>

родительский компонент

<template>
  // 通过v-on向子组件传递一个函数,用户接受返回值
  <VInput :value="valueRef" :maxLength="10" @onInput="onInput" />
</template>

<script lang="ts">
import { defineComponent, ref } from 'vue'
import VInput from '@/components/VInput.vue'

export default defineComponent({
  name: 'Demo',
  components: {
    VInput
  },
  setup() {
    const valueRef = ref('')

    const onInput = (value: string) => {
       // 接受子组件VInput返回的值
      console.log(value)
      // 改变对应的值
      valueRef.value = value
    }

    return {
      valueRef,
      onInput
    }
  }
})
</script>

за этоinputИспользование компонента, я думаю, все определенно не хотят быть такими хлопотными, чтобы получать и изменять значение в родительском компоненте, поэтомуvueпредоставленv-modelдля более быстрого ввода и вывода.

v-model

пройти черезVue3В документации можно найти, что использование этой директивы в некоторой степени изменилось. Раньше мы хотели реализоватьПользовательские компоненты, не являющиеся формамидвухсторонняя привязка, нужно пройтиxxxx.syncЭтот синтаксис реализован, и теперь эта инструкция упразднена, но используется единообразноv-modelэта команда.

родительский компонент

новыйv-modelДвусторонняя привязка нескольких данных также может поддерживаться.

<template>
  <VBtn v-model:value="valueRef" v-model:keyword="keywordRef" />
</template>

Пользовательские компоненты, не являющиеся формами

<template>
  <button @click="clickHandle">click</button>
</template>

export default defineComponent({
  name: 'VBtn',
  props: {
    value: String,
    keyword: String
  },
  setup(props, { emit }) {
     // 省略其他代码
     
     // 用户点击按钮
    const clickHandle = (e: any) => {
      // 省略其他代码
      
      // 修改对应的props的数据
      emit('update:value', value)
      emit('update:keyword', value + '123')
    }
    
    return {
      // ...
    }
  }
})

Вышеупомянутое находится вVue3Введение в API некоторых основных методов связи. существуетVue3обычно используется вComposition ApiВ форме развития вы обнаружите, что не можете использоватьthis.$xxxспособ вызова функции или свойства экземпляра. Теthis.$parent,this.$children,this.$on,this.$emitНе могу дождаться, чтобы использовать его.

что вVue3Как решить эту связь между компонентами? Давайте проанализируем от простых к сложным сценариям один за другим.

Давайте сначала посмотрим, три развитыхformКомпоненты, каково фактическое использование комбинации:

<template>
  <ValidateForm ref="validateFormRef1" :model="state" :rules="rules">
    <ValidateFormItem label="用户名" prop="keyword">
      <ValidateInput
        placeholder="请输入"
        required
        v-model:modelValue="state.keyword"
      />
    </ValidateFormItem>
    <ValidateFormItem label="密码" prop="password">
      <ValidateInput
        placeholder="请输入"
        required
        type="password"
        v-model:modelValue="state.password"
      />
    </ValidateFormItem>
  </ValidateForm>
  <button class="btn btn-primary" @click="submit(0)">提交</button>
</template>

Функциональность всех компонентов имитируетсяElement UIдостигать.

Отец сыну

Родительский компонент передает данные дочернему компоненту двумя способами:

  • v-bind
  • refs получает функцию внутри подкомпонента и напрямую вызывает параметр (здесь он называется методом refs)

метод ссылок

оv-bindНе будем вдаваться в подробности, соответствующее использование было описано в главе об основных операциях. В этом разделе в основном говорится оVue3как пройтиrefПолучение экземпляра подкомпонентного компонента и вызывает функциональный корпус к его подпостам по значению.

Подсборка

<template>
  // 渲染从父级接受到的值
  <div>Son: {{ valueRef }}</div>
</template>

<script lang="ts">
import { defineComponent, ref } from 'vue'

export default defineComponent({
  name: 'Son',
  setup() {
    const valueRef = ref('')
    
    // 该函数可以接受父级传递一个参数,并修改valueRef的值
    const acceptValue = (value: string) => (valueRef.value = value)

    return {
      acceptValue,
      valueRef
    }
  }
})
</script>

родительский компонент

<template>
  <div>sonRef</div>
  <button @click="sendValue">send</button>
  // 这里ref接受的字符串,要setup返回的ref类型的变量同名
  <Son ref="sonRef" />
</template>

<script lang="ts">
import { defineComponent, ref } from 'vue'
import Son from '@/components/Son.vue'

export default defineComponent({
  name: 'Demo',
  components: {
    Son
  },
  setup() {
    // 如果ref初始值是一个空,可以用于接受一个实例
    // vue3中获取实例的方式和vue2略有不同
    const sonRef = ref()

    const sendValue = () => {
      // 可以拿到son组件实例,并调用其setup返回的所有信息
      console.log(sonRef.value)
      
      // 通过调用son组件实例的方法,向其传递数据
      sonRef.value.acceptValue('123456')
    }

    return {
      sonRef,
      sendValue
    }
  }
})
</script>

Здесь вы можете посмотреть на блок-схему:На самом деле, таким образомVue2используется вthis.$refs,this.$childrenМетод очень похож, все напрямую вызывают функцию дочернего компонента, получая экземпляр дочернего компонента. Метод тот же, но вVue3больше не надоthisЭтот черный ящик.

Здесь мы можем посмотреть на это в консолиsonRef.valueчто за штука.

можно найти поrefПолученный экземпляр подкомпонента можно получить вышеsetupВсе возвращаемые переменные и методы, а также некоторые другие внутренние свойства также могут быть получены. Мы можем взглянуть на официальную документациюAPI композиции Vueописание.

В алгоритме исправления Virtual DOM, если ссылка VNode соответствует ссылке в контексте рендеринга, экземпляр элемента или компонента, соответствующий этому VNode, будет назначен этой ссылке. Это выполняется во время процесса монтирования/исправления виртуального DOM, поэтому ссылки на шаблоны доступны только после инициализации рендеринга.

сводка по методу ref

преимущество:

  1. Родительский компонент может быстроконечно существуютдочерние компоненты передают данные

  2. Передаваемые параметры не ограничены, а способ передачи более гибкий

недостаток:

  1. Подкомпонент, полученный с помощью ref, должен быть определен как существующий (неопределенное существование: например, подкомпонент в слоте,v-ifподкомпонент управления)
  2. Подкомпоненты также должны реализовывать методы, которые принимают параметры.

Потомки отца

Как правило, существует два способа передачи значений на уровень глубины:

  • provide / inject
  • vuex

provide / inject

Когда вы видите слово «глубокий», первое, что приходит вам на ум, этоVue2серединаprovide / injectопции. Да, эта логика вvue3То же самое относится и к этим двум параметрам, которые становятся двумя методами.

provideПозволяет нам передать часть данных всем компонентам-потомкам текущего компонента, и все компоненты-потомки могут передатьinjectЭтот метод определяет, принимать ли данные.

Грубая схема выглядит следующим образом:

Практические сценарии применения

Существует два основных сценария применения: один — когда параметр или функция передаются в глубину, а другой — когда параметр передается неопределенному компоненту в слоте.

Сосредоточьтесь на передаче параметров компонентам в слотах. Сначала реализуйте самый внешнийValidateFormКомпонент, который в основном отвечает за принятие всех данных формы и правил проверки для всех данных формы. Он обеспечивает слот внутри для некоторых неопределенных компонентов. есть еще одинValidateFormItemКомпонент может принимать имя поля и точно знать, какое поле необходимо проверить по этому имени поля (советы: функция на самом деле такая же, какelement-uiаналогичный).

Компонентная разработка требует разделения параметров и функций, поэтому мы проектируем следующим образом:

  • ValidateForm:model,rules, просто примите данные и правила проверки всей формы
  • ValidateFormItem:prop, просто примите имя поля, просто знайте, какое поле вам нужно проверить
<template>
  <ValidateForm ref="validateFormRef" :model="formData" :rules="rules">
    <ValidateFormItem label="用户名" prop="keyword">
      <!-- field组件 -->
    </ValidateFormItem>
    <ValidateFormItem label="密码" prop="password">
      <!-- field组件 -->
    </ValidateFormItem>
  </ValidateForm>
</template>

еслиValidateFormItemкомпоненты должны пройтиpropЧтобы проверить поле, ему необходимо получить данные этой формы черезformData[prop]чтобы получить значение этого поля, то этоformDataОткуда это? Во-первых, невозможно написать всеValidateFormItemКомпоненты передаются копии. Потому что в реальном развитии мы не можем быть уверены, чтоValidateFormсколько писатьValidateFormItemКомпоненты, если вы вручную передаете форму данных каждый раз, когда пишете их, это добавит много избыточного кода и создаст проблемы. Следовательно, поValidateFormЭтот компонент принимается и распространяется самостоятельно.

ValidateForm

так что нам нужноValidateFormраспределять данные вниз.

<template>
  <form>
    <slot></slot>
  </form>
</template>

<script lang="ts">
import { defineComponent, provide } from 'vue'

export const modelKey = Symbol()
export const rulesKey = Symbol()


export default defineComponent({
  name: 'ValidateForm',
  props: {
    model: {
      type: Object
    },
    rules: {
      type: Object
    }
  },
  setup(props) {
    // 向后代发放数据
    provide(modelKey, props.model)
    provide(rulesKey, props.rules)

    return {}
  }
})
</script>

ValidateFormItem

ValidateFormItemПримите данные, переданные выше.

<script lang="ts">
import { defineComponent, reactive, inject, provide } from 'vue'
import { modelKey, rulesKey } from './ValidateForm.vue'


export default defineComponent({
  name: 'ValidateFormItem',
  props: {
    label: String,
    required: {
      type: Boolean,
      default: false
    },
    prop: String
  },
  setup(props) {
    // 接受ValidateForm传下来的数据
    const model = inject<any>(modelKey, ref({}))
    const rules = inject<any>(rulesKey, ref({}))
    
    // 根据props.prop在model和rules分别取出需要 校验的数据 和 校验的规则
    console.log(model[props.prop])
    console.log(rules[props.prop])
    // 数据校验的逻辑

    return {
      //...
    }
  }
})
</script>

обеспечить / ввестиСводка

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

vuex

vuexвсегда былvueКачественное решение для обмена данными компонентов на разных уровнях экосистемы. Его можно не только применять в отношениях родитель-потомок, это очень хорошее решение между компонентами потомок-отец, предок-потомок, потомок-предок и братья и сестры. Потому что это централизованный режим управления состоянием. Его реализация также носит ответный характер. Просто упомянуть здесьVue3как используется.

Создаватьstore

import { createStore } from 'vuex'

export enum Mutarions {
  SET_COUNT = 'SET_COUNT'
}

export default createStore({
  state: {
    count: 231
  },
  getters: {
    count: state => state.count
  },
  mutations: {
    [Mutarions.SET_COUNT]: (state, num: number) => (state.count = num)
  }
})

родительский компонент

<template>
  <div>father</div>

  <Son ref="sonRef" />
</template>

<script lang="ts">
import { defineComponent, ref } from 'vue'
import Son from '@/components/Son.vue'
import { useStore } from 'vuex'
import { Mutarions } from '@/store/index'

export default defineComponent({
  name: 'Father',
  components: {
    Son
  },
  setup() {
    const valueRef = ref(100)

    const store = useStore()

    store.commit(Mutarions.SET_COUNT, valueRef.value)

    return {}
  }
})
</script>

Подсборка

<template>
  <div>Son: {{ count }}</div>
</template>

<script lang="ts">
import { defineComponent, computed } from 'vue'
import { useStore } from 'vuex'

export default defineComponent({
  name: 'Son',
  setup() {
    const store = useStore()
    const count = computed(() => store.getters.count)

    return {
      count
    }
  }
})
</script>

сын к отцу

Ребенок может передать данные родителю тремя способами:

  • v-on
  • метод ссылок
  • центр событий

метод ссылок

пройти черезrefТо же самое относится к передаче данных родителю. Конкретная идея: Внутри подкомпонента реализована функция, которая может возвращать значение. родительский компонент черезrefПосле получения экземпляра подкомпонента вызовите этот метод, чтобы получить требуемое возвращаемое значение.

Вот посмотрите на реальный сценарий приложения, мы надеемсяValidateFormКомпонент проверяет все элементы формы ниже, а затем возвращает состояние проверки внутри компонента через функцию.

родительский компонент

<template>
  <ValidateForm ref="validateFormRef" :model="formData" :rules="rules">
    <ValidateFormItem label="用户名" prop="keyword">
      <!-- field组件 -->
    </ValidateFormItem>
    <ValidateFormItem label="密码" prop="password">
      <!-- field组件 -->
    </ValidateFormItem>
  </ValidateForm>
</template>

<script lang="ts">
import { defineComponent, ref } from 'vue'

export default defineComponent({
  name: 'demo',
  setup() {
    // 省略部分代码
    
    const validateFormRef = ref()
    
    // 通过validate拿到ValidateForm组件内部的一个验证状态
    if (this.validateFormRef.validate()) {
      // 表单验证成功后,做后续的操作
    }

    return {
      validateFormRef
    }
  }
})
</script>

ValidateForm

<template>
  <form>
    <slot></slot>
  </form>
</template>

<script lang="ts">
import { defineComponent } from 'vue'

export default defineComponent({
  name: 'ValidateForm',
  setup() {
    const validate = async () => {
      let result = false
      // 调用插槽下所有ValidateFormItem组件内部的校验方法
      //(tips:至于如何调用,后面的事件中心会重点说)
      // 如果有一个校验方法返回的是false就直接返回false
      // 如果都为true就返回一个true

      return result
    }

    return {
      validate
    }
  }
})
</script>

Вот примерная блок-схема:

Этот метод также может получать данные внутри подкомпонента, что аналогично функции замыкания.

центр событий

Почему этот способ связи приведен сюда? Потому что я думаю, что будет очень уместно использовать центр событий в следующем актуальном случае. В предыдущем подразделе мы оставили яму, т.е.ValidateFormЕсли компонент хочет проверить, проходит ли вся форма, он должен найти способ сделать так, чтобы каждыйValidateFormItemВерните ему результат внутренней проверки.

Во-первых, есть две проблемы

  1. ValidateFormСледующие компоненты устанавливаются через прорези, поэтому они не могут пройти черезrefспособ получить экземпляр каждого элемента подчиненной формы, поэтому нет способа получить каждыйValidateFormItemстатус проверки.
  2. В разделе выше есть картинка, которая показываетrefПолученный экземпляр компонента. можно найти, можно найти$parentсвойства, но нет$childrenАтрибуты. Это неловко, мы не можем быть такимиVue2тоже самоеValidateFormпрошедший$childrenПолучите экземпляр каждого дочернего компонента.

Решения

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

  1. существуетValidateFormКогда экземпляр инициализирован, создайте центр событийEmitterНапример, он может зарегистрировать событие, когда это событие выполняется, может принять функцию и сохранить в очереди.
  2. положи этоEmitterпройти черезprovideпередается потомкам, чтобы гарантировать, что центр событий находится в другомValidateFormкомпоненты независимы. Другими словами, если вы напишете более одногоValidateForm, их концентраторы событий не мешают друг другу.
  3. существуетValidateFormItemиспользуется вinjectПолучите поле формы, в котором вы находитесьEmitter, при монтировании выполнитьEmitterсобытия наvalidateфункция, переданнаяValidateForm, который кэширует метод в очереди.
  4. ValidateFormКогда проверка выполнена, все функции проверки в очереди могут быть выполнены, и может быть получен результат проверки.

Конкретная реализация кода:

сначала реализоватьEmitterкласс концентратора событий

import { EmitterHandles } from '@/type/utils'

export class Emitter {
  // 存放事件函数
  private events: EmitterHandles = {}

  // 用于注册事件
  on(eventName: string, eventHandle: Function) {
    this.events[eventName] = eventHandle
  }

  // 删除事件
  off(eventName: string) {
    if (this.events[eventName]) {
      delete this.events[eventName]
    }
  }

  // 触发事件
  emit(eventName: string, ...rest: any[]) {
    if (this.events[eventName]) {
      this.events[eventName](...rest)
    }
  }
}

Когда центр событий будет реализован, давайте улучшим его здесьValidateFormкод

<script lang="ts">
import { defineComponent, nextTick, provide } from 'vue'
import { Emitter } from '@/utils/emitter'

type ValidateFunc = () => boolean

export const emitterKey = Symbol()
export const modelKey = Symbol()
export const rulesKey = Symbol()


export default defineComponent({
  name: 'ValidateForm',
  props: {
    model: {
      type: Object
    },
    rules: {
      type: Object
    }
  },
  setup(props) {
    // 将表单数据和验证规则传递给后代
    provide(modelKey, props.model)
    provide(rulesKey, props.rules)
    
    // 创建事件中心的实例
    const emitter = new Emitter()
    // 将事件中心传递给后代
    provide(emitterKey, emitter)

    // 接受formItem组件返回的验证函数
    // 并且将其存起来
    emitter.on('acceptValidate', (validateFunc: ValidateFunc) => {
      validateList.push(validateFunc)
    })
   
    // 用于接受保存后代返回的验证方法
    const validateList: ValidateFunc[] = []

    // 验证所有数据的状态
    const validate = () => {
      // 执行每一个子表单发送过来的验证方法
     return validateList.map(fn => fn()).every(valid => valid)
    }

    return {
      validate
    }
  }
})
</script>

хорошо, теперь достигнутоvalidateFormЛогика, давайте напишем еще разvalidateFormItemлогика

<template>
  <div class="form-group">
    <label v-if="label" class=" col-form-label">{{ label }}</label>
    <slot></slot>
    <small v-if="error.isError" class="invalid-feedback">
      {{ error.errorMessage }}
    </small>
  </div>
</template>

<script lang="ts">
import { Emitter } from '@/utils/emitter'
import { defineComponent, reactive, inject, onMounted, provide } from 'vue'
import { emitterProviderKey, modelKey, rulesKey } from './ValidateForm.vue'

export default defineComponent({
  name: 'ValidateFormItem',
  props: {
    label: String,
    required: {
      type: Boolean,
      default: false
    },
    prop: String
  },
  setup(props) {
    // 接受Emitter事件中心
    const emitter = inject<Emitter>(emitterProviderKey)
    // 接受数据和校验规则
    const model = inject<any>(modelKey)
    const rules = inject<any>(rulesKey)

    const error = reactive({
      isError: false,
      errorMessage: ''
    })
    
    // 校验对应的字段数据
    const validateField = () => {
      const prop = props.prop
      if (prop && model && rules && rules[prop]) {
        const result = rules[prop].some((item: any) => {
          if (!item.validator(model[prop])) {
            console.warn(`${prop}:${item.message}`)
            error.isError = true
            error.errorMessage = item.message
            return true
          }
        })
        return !result
      }
      return true
    }
   
   
    // 当组件挂载的时候,将自身的校验函数发送给ValidateForm组件
    onMounted(() => {
      emitter && emitter.emit('acceptValidate', validateField)
    })

    return {
      error
    }
  }
})
</script>

Для того, чтобы более подробно понять вышеописанный процесс, вот принципиальная схема:

  1. Регистрируйтесь на мероприятия, распространяйте концентраторы событий

  1. Выполнить событие, отправить функцию проверки

Суть всего процесса заключается в том, что компонент верхнего уровня создает и распределяет центр событий, а также регистрирует функцию прослушивания событий. Компоненты-потомки выполняют событие и отправляют информацию, а компонент верхнего уровня повторно использует информацию.

Tips

Еще один момент здесь, при использованииEmitterВ центре этого события былValidateFormизsetupЭто не использование глобального центра событий для его создания и распространения. Нравится эта статья от большого парняКраткое изложение методов связи компонентов Vue и сценариев их примененияКак подытожено в , форма шины событий имеет фатальный недостаток: если на странице есть несколько публичных компонентов, нам нужно передать данные только одному из них, но каждый публичный компонент привязан к методу получения данных, тогда будет путаница. Однако наша шина событий — не глобальная, а концентратор событий внутри одной области.

Поскольку центр событий создается внутри текущего компонента и используетprovideПубликуется, чтобы только потомки текущего компонента могли использовать этот концентратор событий. Поэтому, даже если на одном лице написано больше одногоValidateForm, их контрольные суммы независимы.

<template>
  <ValidateForm ref="validateFormRef1" :model="formData1" :rules="rules">
    <ValidateFormItem label="用户名" prop="keyword">
      <!-- field组件 -->
    </ValidateFormItem>
    <ValidateFormItem label="密码" prop="password">
      <!-- field组件 -->
    </ValidateFormItem>
  </ValidateForm>
  
    <ValidateForm ref="validateFormRef2" :model="formData2" :rules="rules">
    <ValidateFormItem label="用户名" prop="keyword">
      <!-- field组件 -->
    </ValidateFormItem>
    <ValidateFormItem label="密码" prop="password">
      <!-- field组件 -->
    </ValidateFormItem>
  </ValidateForm>
</template>

Схема:

Сводка центра событий

преимущество:

  1. Может быть решенVue3нельзя использоватьthis.$childrenЭта проблема
  2. Может использоваться гибко и не ограничивается уровнем компонентов
  3. Этот способ общения не ограничен рамками

недостаток:

  1. Необходимо контролировать объем центра событий
  2. Необходимо контролировать спецификацию имени события

Расширенный центр событий

Потому чтоVue3изComposition APIсередина,vueФункция API более детализирована. Мы можем сделать индивидуальную трансформацию центра событий.

может быть представленreactive, refПомогая нашему центру событий поддерживать оперативные данные внутри, мы можем обновлять соответствующее представление, когда центр событий выполняет определенные действия при общении. также можно импортироватьcomputedРеализует функцию вычисляемых свойств.

import { reactive, ref, computed } from 'vue'

export class Emitter {
  // 响应式的数据中心
  private state = reactive({})
  private events: EmitterHandles = ref({})
  
  // 记录当前事件中心 事件的数量
  private eventLength = computed(() => Object.keys(events.value).length)
  
  // 省略部分代码
}

Присоединяйсяwatch,watchEffectРеализуйте функцию мониторинга данных, чтобы сделать определенные логические действия. я думаюComposition APIа такжеReact Hooks ApiОба они очень мощные, потому что позволяют нам использовать функциональные функции в качестве строительных блоков для сборки любого приложения, которое мы хотим.

Глубинные потомки общаются наверху, братья общаются

Я думаю на самом деле другие сценарии, способы общения в основном те же, так называемый стереотип. Потомки передают значения предкам, или можно использовать одноуровневые компонентыvuexили事件中心Путь. Иерархия одного уровня или смежная иерархия, которую вы можете использоватьref,$parentи так далее.

наконец

Я личноVue3Это все еще очень оптимистично.В настоящее время для некоторых старых проектов компании я также думаю, как его использовать.Vue3провести его рефакторинг. Тогда я тоже только что прочитал статью лидера сообщества, которая, безусловно, очень интересна, поэтому и пришел написать интересную статью.Vue3Резюме общения 😂, может быть много не совсем к месту мест.

Если у вас есть какие-либо ошибки или дополнения, пожалуйста, оставьте сообщение в области комментариев.Если вы считаете, что это нормально, чтобы помочь вам, пожалуйста, поставьте палец вверх, 🙏 Спасибо всем, милые мальчики и девочки.