Коммуникация компонентов Vue — меры предосторожности и обзор опыта

внешний интерфейс JavaScript Vue.js Vuex vue-router

написать впереди

Связь между компонентами является очень распространенной частью фактической разработки. То, как ее использовать, оказывает очень практическое влияние на общий дизайн, разработку и спецификацию проекта. Я глубоко понимаю это при разработке проекта. компоненты Несколько способов обсуждения соответствующих сценариев использования

В статье анонсируется соответствующая сцена

  • Передача данных между родительскими->дочерними компонентами
  • Передача данных между дочерними -> родительскими компонентами
  • Передача данных между родственными компонентами
  • Глубокая вложенность компонентов, передача данных между компонентами-предками и компонентами-потомками

Предварительный просмотр технологии, связанной со статьейprop, emit, bus, vuex, URL-адрес маршрута, предоставление/внедрение, дочерние элементы/$parent, $attrs/inheritAttrs

Примечание. Следующее введение и среда кода:vue2.0+, vue-кли2

Передача данных между родительскими->дочерними компонентами

Связь между родительским и дочерним компонентами является наиболее часто используемой и наиболее важной для разработки.Вы должны знать, что связь между родителем и дочерним элементом использует свойства для передачи данных, например:

//父组件,传递数据
<editor :inputIndex="data" :inputName="王文健"></editor>
//子组件,接受数据,定义传递数据的类型type与默认值default
    props: {
        inputIndex: {
            type: Object, 
            default: function(){
                return {}
            }
        },
        inputName: {
            type: String,
            default: ''
        },

Примечания:

  1. Когда родительский компонент передает данные, это похоже на запись атрибута в теге.Если данные, которые должны быть переданы, находятся в данных, естественно добавить их до передачи атрибута.v-bind:, что если вы передадите известное фиксированное значение

    • строкастатическийможет быть передан напрямую без добавления атрибутаv-bind
    • числа, логические значения, объекты, массивы, поскольку это выражения js, а не строки, поэтому, даже если они передаются статически, вам нужно добавитьv-bind, введите данныеdataцитируется в,
  2. Если данные, переданные свойством дочернему компоненту, являются объектом, следует отметить, что переданные данные являютсяссылка на объект, хотя родительский и дочерний компоненты кажутся разделенными, в конце концов все они находятся под одним и тем же объектом

    • Если значение свойства, переданного дочернему компоненту, используется только как начальное значение и не изменится в родительском компоненте.dataиспользуется в
    • Если данные, переданные в проп дочернего компонента, будут изменены в родительском компоненте, поместите его ввычисляемое свойствоИспользуйте для мониторинга изменений.Потому что, если объект передается, только изменение одного из свойств ниже не будет оперативно обновляться в подкомпоненте.Если подкомпонент необходимо оперативно обновлять при изменении данных, его можно поместить только в вычисляемый или глубокий копировать глубоко с помощью watch :true для прослушивания изменений
    • Конечно, если вам нужно передать изменения данных через prop в дочернем компоненте для выполнения каких-то операций, то в вычисляемом будет сообщено предупреждение, потому что вычисляемое свойствоНе рекомендуется изменять данные, лучше просто сделать расчет. Если вам нужно работать с данными, вы можете написать слушателя вwatch(обратите внимание на глубокую копию) или используйте вычисляемыйgetа такжеsetКак показано ниже:
      计算属性.png
  • Но проблема возникает снова: если вы передаете объект, и вам нужно манипулировать данными, переданными в дочернем компоненте, то это в родительском компонентеданные также изменятся,потому что то, что вы передаете, это просто ссылка, даже если вы скопируете данные реквизита вdataТо же самое и в , присваивание в любом случае является присваиванием по ссылке,Вы можете только сделать глубокую копию объекта и создать копию для продолжения операции., вы можете использовать метод JSON, чтобы сначала преобразовать строку в объект, что более удобно,
  • Поэтому при передаче данных между родительским и дочерним компонентом вы должны сначала подумать, как использовать данные, иначе вы столкнетесь со многими проблемами или модифицируете данные в родительском компоненте в дочернем компоненте, что очень сложно.скрытыйи опасно

Передача данных между дочерними -> родительскими компонентами

В vue дочерний элемент передает данные родителю, обычно использует пользовательское событие **$emit**, прослушивает это событие в родительском компоненте и записывает соответствующую логику в обратном вызове.

// 父组件监听子组件定义的事件
 <editor :inputIndex="index" @editorEmit='editorEmit'></editor>
// 子组件需要返回数据时执行,并可以传递数据
this.$emit('editorEmit', data)

Итак, вопрос в том, действительно ли мне необходимо возвращать эти данные родительскому компоненту?Я могу использовать пользовательское событие для выполнения, когда дочерний компонент хочет передать данные или данные, переданные дочернему компоненту, изменяются и должны быть повторно -прошел, потом еще Сюжеты,Родительскому компоненту требуется часть данных от дочернего компонента, но дочерний компонент не знает или не имеет возможности предоставить родительскому компоненту, когда родительский компонент этого хочет., то в это время используется опция компонентаref:

<editor ref="editor" @editorEmit='editorEmit'></editor>

  • Родительский компонент определяет атрибут ref в теге и вызывает его непосредственно в js.this.$refs.editorЭто вызов всего подкомпонента, а все содержимое подкомпонента можно вызвать через ref.Конечно, мы не рекомендуем это, потому что это сделает данные очень запутанными.
  • Таким образом, мы можем определить функцию в дочернем компоненте для вызова родительского компонента,, например, мы возвращаем определенные данные в данных дочернего компонента в этой функции, ** когда родительский компонент хочет получить эти данные, он будет напрямую вызывать ref для выполнения этой функции для получения этих данных, ** это может адаптироваться к большая часть сцены, да и логика тоже немного понятнее
  • Кроме того, ref можно использовать и для передачи данных от родителя к дочернему.В родительском компоненте нужно было вызвать большое количество одного и того же дочернего компонента, и проп-данные, передаваемые каждым вызовом, были разными, и передаваемые данные будет меняться в соответствии с последующими операциями, поэтому мне нужно определить много связанных данных и изменить их, яВы можете напрямую использовать ref для вызова функции подкомпонента и напрямую передавать данные в подкомпонент в виде параметров, логика понятна
  • Если вы вызываете базовый компонент, вы можете вызвать ref в родительском компоненте для выполнения различных функциональных интерфейсов, представленных в базовом компоненте, таких как отображение, исчезновение и т. д.

Передача данных между родственными компонентами

Связь между одноуровневыми компонентами в Vue очень неудобна или не поддерживается, так какие методы связи существуют в родительском и дочернем компонентах?

  • Параметры URL-адреса маршрута
    • В традиционной разработке мы часто помещаем данные, которые необходимо передать по страницам, за URL-адресом, а при переходе на другую страницу мы можем напрямую получить строку URL-адреса для получения нужных параметров, и мы можем сделать то же самое, когда Vue кросс- компоненты.
      // router index.js 动态路由
      {
         path:'/params/:Id',
         component:Params,
         name:Params
      }
      
      // 跳转路由
      <router-link :to="/params/12">跳转路由</router-link>
      
    • В компоненте после перехода используйте $route.params.id, чтобы получить параметр id равный 12, но это подходит только для передачи относительно небольших данных, чисел и т.п.
  • Автобусное сообщение

Определите bus.js вне компонента в качестве моста для связи между компонентами, который подходит для небольших компонентов, которым не требуется vuex и требуется связь между компонентами-близнецами.

  1. Добавьте следующее в bus.js

      import Vue from 'vue'
      export default new Vue
    
  2. Вызов bus.js в компоненте для передачи данных через пользовательские события

      import Bus from './bus.js' 
      export default { 
          methods: {
             bus () {
                Bus.$emit('msg', '我要传给兄弟组件们')
             }
          }
      }
    
  3. Прослушивание событий в родственных компонентах для получения данных

        import Bus from './bus.js'
        export default {
            mounted() {
               Bus.$on('msg', (e) => {
                 console.log(e)
               })
             }
           }
    

Примечание: Приведенные выше два сценария использования не высоки, поэтому я лишь кратко упомяну о них. Эти два пункта были написаны давно. Вышеприведенные примеры собраны непосредственно из Интернета. Если есть какая-то ошибка, пожалуйста, поправьте меня

  • Централизованное управление состоянием VuexVuex – это инструмент централизованного управления состоянием для Vue. Для крупномасштабных приложений очень удобно управлять данными унифицированным и централизованным образом. Я не буду подробно рассказывать здесь об использовании Vuex, а лишь упомяну о проблемах, возникающих при использовании. .
    • Спецификация: это очень важно для формулировки крупномасштабных спецификаций приложений, разработанных несколькими людьми.Для vuex, с которым все соприкасаются, должна быть четкая и строгая спецификация для модификации данных и вызова данных.Условия эксплуатации

      1. Подмодуль Vuex: поддерживать свои собственные данные vuex между разными модулями проекта.
      2. Ограничить вызовы: разрешить действиям только манипулировать данными, геттеры получают данные, использовать mapGetters, вспомогательные функции mapActions для вызова данных
        vuex.png
    • Также ведутся споры о сценариях использования vuex.Некоторые люди думают, что нормальные компоненты должны передавать значения между родительским и дочерним компонентами.Даже если дочернему компоненту нужно сделать данные в vuex, они должны быть получены родительский компонент, а затем передается дочернему компоненту, но некоторые. Когда компоненты глубоко вложены, это не удобный способ разрешить только родительскому компоненту получать данные, поэтому возникает новая проблема в передаче значений между мета-предками. компоненты и дочерние компоненты, а на официальном веб-сайте vue также есть некоторые решения, а именно:

Передача данных между компонентами-предками и компонентами-потомками

provide/injectВ дополнение к обычной передаче значения компонента родитель-потомок, vue также обеспечивает предоставление/внедрение

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

Официальный сайт экземпляра

// 父级组件提供 'foo'
var Provider = {
  provide: {
    foo: 'bar'
  },
  // ...
}

// 子组件注入 'foo'
var Child = {
  inject: ['foo'],
  created () {
    console.log(this.foo) // => "bar"
  }
}
  • Параметр предоставления должен быть объектом или функцией, которая возвращает объект. Этот объект содержит свойства, которые можно внедрить в его потомков.
  • массив строк или Объект, ключ которого является именем и значением локальной привязки:
    • Ключ (строка или символ) для поиска в доступном внедряемом контенте или Объект, который:
      • Свойство from — это ключ (строка или символ) для поиска в доступном внедряемом содержимом.
      • Атрибут по умолчанию — это значение, используемое в случае перехода на более раннюю версию.

Совет: привязки обеспечить и внедрить не являются реактивными. Это сделано намеренно. Однако, если вы передаете прослушиваемый объект, свойства объекта по-прежнему реагируют.Конкретные детали перенесены во вступление, связанное с vue.Talent.v UE JS.org/V2/API/#pro…

Provide/inject не применялся в проекте, попробуем позже


Добавлен $attrs/inheritAttrs

Напомните друзьям, чтобы дополнить использование $attrs

Сцены: передавать значения между компонентами-предками и дочерними компонентами

  • Если это реквизит, каждый компонент между подкомпонентом и компонентом-предком должен принимать эти данные через реквизит, а затем передавать их следующему подкомпоненту, что очень хлопотно, а связанная глубокая программа раздувается.
  • Если вы используете vuex, это кажется немного излишним, поэтому неплохо использовать $attrs для прямого получения данных о предках.

Содержит привязки свойств (кроме класса и стиля), которые не распознаются (и не получаются) как свойства в родительской области. Когда компонент не объявляет никаких реквизитов, все привязки родительской области (кроме класса и стиля) включаются сюда и могут быть переданы внутренним компонентам через v-bind="$attrs" - очень полезно при создании высокоуровневых компонентов.

Выше приведено объяснение $attrs на официальном сайте.Я был сбит с толку, когда впервые увидел его.Его не сложно вернуться и попробовать,и он больше подходит для глубокой вложенности компонентов.Проблема передачи значений от компонентов-предков к компонентам-потомкам

Это означает, что родительский компонент передается дочернему компоненту, данные, которые дочерний компонент не принимает, будут помещены в $attrs, а дочерний компонент может быть получен напрямую с помощью this.$attrs. Если вы переходите от родителя -> внука, добавляете v-bind='$attrs' к дочернему компоненту и передаете все данные, полученные дочерним компонентом от родительского компонента без реквизита, дочернему компоненту, см. следующий код для деталей.

использовать:

предковый компонент

// 祖先组件
// 在祖先组件中直接传入output和input
<template>
  <div>
    <child1 :output='output' :input="input"></child1>
  </div>
</template>
<script>
import child1 from './child1.vue'
export default {
  components: {
    child1
  },
  data () {
    return {
      input: 'jijijijjijiji',
      output: {
        name: '王文健',
        age: '18'
      }
    }
  }
</script>

Подсборка

<template>
  <div
    <h1>{{input}}</h1>
    <child2 :child="child" v-bind='$attrs'></child2>
  </div>
</template>
<script>
import child2 from './child2.vue'
export default {
  components: {
    child2
  },
  props: {
    input: [String]
  },
  data () {
    return {
      child: 'child1child1child1child1s'
    }
  },
// 默认为true,如果传入的属性子组件没有prop接受,就会以字符串的形式出现为标签属性
// 设为false,在dom中就看不到这些属性,试一下就知道了
  inheritAttrs: false,
  created () {
    // 在子组件中打印的$attrs就是父组件传入的值,刨去style,class,和子组件中已props的属性
    console.log(this.$attrs)  // 打印output
  }
}
</script>

компонент внука

<template>
  <div>
    {{$attrs.output.name}}
  </div>
</template>
<script>
export default {
  created () {
    // 打印output和child
    console.log(this.$attrs)
  }
}
</script>

Это кажется очень полезным. Я не использовал его в конкретном проекте. Я думаю, что он скоро будет использован. Если у вас есть какие-либо вопросы, пожалуйста, оставьте сообщение.

$children/$parent

  • Конечно, вы можете напрямую использовать $children/$parent для получения экземпляра дочернего компонента или экземпляра родительского компонента (если есть) текущего компонента, а также вы можете выполнять над ним некоторые операции, но это не рекомендуется.

  • Вы также можете поместить его в localStorage, sessionStorage, cookie и т. д. Конечно, вы также можете общаться между компонентами локально.

напиши в конце

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


Если оригинал статьи воспроизводится, просьба указывать ссылку на оригиналblog.Wangwenjie.com/index.PHP/Ах…