Vue: должен ли vuejs2.0 сохранять api событий $ broadcast, $ dispatch? В 2.0 нет хорошего решения для двухточечной связи между родителями и детьми.

Созданный на 1 сент. 2016  ·  41Комментарии  ·  Источник: vuejs/vue

@ yyx990803 ,
Привет, основная команда vuejs,
Я изо всех сил пытаюсь найти хорошее решение для точечной связи между родительскими дочерними компонентами с vuejs2.0.
Поскольку vuejs2.0 устарел api $ broadcast, $ dispatch, мне очень сложно найти альтернативное решение $ broadcast, $ dispatch предоставляет функцию шины событий vuejs2.0.
Я написал ветку на форуме по этой теме здесь , и я хотел бы вставить ее сюда для дальнейшего обсуждения.

ПОЖАЛУЙСТА, НЕ ЗАКРЫВАЙТЕ ЕЕ, ЕСЛИ У ВАС нет хорошей идеи или решения на vuejs2.0.

<pcom id=1>
    <soncoma></soncoma>
    <soncomb></soncomb>
</pcom>
<pcom id=2>
    <soncoma></soncoma>
    <soncomb></soncomb>
</pcom>

В приведенном выше коде, когда дочерний элемент pcom1, например, soncoma $, выдает событие, скажем,

bus.$emit('son-coma-event',somedata)

на pcom мы слушаем это событие с помощью

bus.$on('son-coma-event',function(){})

Я хочу, чтобы pcom1 обрабатывал это событие, но, к сожалению, pcom2 тоже справится с этим.
Как справиться с этим состоянием?

Один из обходных путей в моем приложении - использовать родительский элемент this. $ В качестве шины событий.
У ребенка:

this.$parent.$emit('some-event',someData)

В родительском:

{
   created(){
       this.$on('some-event',function(){})
}

Отрицательный момент для вышеуказанного обходного пути:

  1. мы много спариваем по родительско-дочерним отношениям;
  2. он не работает, если есть более глубокий уровень родительско-дочерних уровней;

В некоторых более сложных условиях будет сложнее найти хорошее решение для настраиваемой системы событий, например, рекурсивный компонент

 <pcom>
    <recursivechild>
             <recursivechild>
                          <recursivechild>
                          </recursivechild>
             </recursivechild>
    <recursivechild>
</pcom>

 <pcom>
    <recursivechild>
             <recursivechild>
                          <recursivechild>
                          </recursivechild>
             </recursivechild>
    <recursivechild>
</pcom>

как рекурсивный ребенок общается со своим прямым компонентом pcom?
Пожалуйста, выскажите свою идею или точку зрения по этим темам.
Спасибо ~!

discussion

Самый полезный комментарий

@rhyek Я хотел бы высказать свое мнение о паре поднятых вами вопросов. Поскольку обсуждение уже коснулось ряда тем, я хотел бы вернуться к основам того, почему мы устарели $ diospatch и $ broacast:

1. неявная связь.

Если у вас есть родитель и глубоко вложенный дочерний элемент, который отправляет событие, нет никакого способа вывести эту взаимосвязь из кода (и то же самое верно для $broadcast , очевидно.)

Если вы посмотрите на другие изменения и устаревания, которые мы представили в Vue 2.0, вы можете понять, что удаление неявного поведения в пользу явных альтернатив является общей темой, и отказ от $dispatch подходит как раз для этого.

Пример:

// parent
events: {
  'some-event': function () { ... }
}

// deeply nested child:
$dispatch('some-event')

Это нормально, когда у родителя есть только один прямой потомок, но в этом случае $emit() со слушателем в шаблоне тоже не является реальной дополнительной работой.

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

Вы говорите, что вам нравятся $ dispatch и $ broadcast, потому что вам не нужно передавать их через другие компоненты. И я могу согласиться с тем, что это проще - но мы не сталкивались со многими ситуациями, когда это было действительно необходимо, или, скорее, если бы существовала такая цепочка пропуска события, скорее всего, данные были бы изменены / добавлено / во время этой поездки компонентом между ними.

2. Названия событий

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

// parent
events: {
  'close': function () { ... }
}

// deeply nested child 1:
$dispatch('close')
// deeply nested child 2:
$dispatch('close')

..и если эти дети являются сторонними библиотеками, вы сейчас облажались. или вам нужно поймать событие в каком-то компоненте посередине, чтобы просто переименовать его, прежде чем вы $dispatch() дальше до родителя. И не забудьте прокомментировать это, потому что кто-то, глядя на этот код, может подумать, почему вы не делаете ничего другого с событием, кроме его переименования.

Использование слушателей $ emit и шаблонов не вызывает этой проблемы. вы можете везде использовать простые короткие имена событий, они не будут конфликтовать друг с другом, поскольку каждое событие имеет собственный обратный вызов, прикрепленный к шаблону @close="callback ".

Я просто хочу, чтобы вы не отказались от * выбора * для использования любой парадигмы,

Если бы мы думали, что обе парадигмы могут работать одинаково хорошо, мы бы относились к ним одинаково. Но мы так не думаем по указанным выше и другим причинам.

Поэтому мы стараемся подтолкнуть пользователей к методам, которые, по нашему мнению, работают лучше всего, и при этом оставляем способ обойти это с помощью метода «глобальной шины».

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

Может быть, вы можете привести пример, в котором, по вашему мнению, вам лучше всего подходят $ dispatch и $ broadcast, и я пытаюсь показать вам, как «наш» подход может улучшить ситуацию?

Все 41 Комментарий

Поскольку это общее обсуждение предложения, я еще не создал скрипку. Если требуется, я хотел бы создать для демонстрации.
спасибо ~!

Это уже было оправдано в изменениях 2.0.

Вот копия:

Как бороться с устареванием $dispatch и $broadcast ?

Причина, по которой мы не рекомендуем $dispatch и $broadcast заключается в том, что потоки событий, зависящие от древовидной структуры компонентов, могут быть трудными для понимания того, когда дерево компонентов становится большим (проще говоря: это не так. хорошо масштабируется в больших приложениях, и мы не хотим беспокоить вас позже). $dispatch и $broadcast также не решают проблему связи между одноуровневыми компонентами. Вместо этого вы можете использовать шаблон, аналогичный EventEmitter в Node.js : централизованный концентратор событий, который позволяет компонентам обмениваться данными, независимо от того, где они находятся в дереве компонентов. Поскольку экземпляры Vue реализуют интерфейс генератора событий, вы можете использовать для этой цели пустой экземпляр Vue:

var bus = new Vue()
// in component A's method
bus.$emit('id-selected', 1)
// in component B's created hook
bus.$on('id-selected', function (id) {
 // ...
})

Этот шаблон может служить заменой $dispatch и $broadcast в простых сценариях. Но для более сложных случаев рекомендуется ввести специальный уровень управления состоянием с помощью Vuex .

Пример, показанный в руководстве по обновлению, такой же, как вы говорите.

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

@posva , спасибо за информацию. автобусный концентратор действительно хорошо работает в простой связи между отдельными компонентами. Если есть несколько компонентов с одним и тем же типом компонентов, возникнет проблема, к сожалению, это нормальный случай. Во многих случаях я хочу использовать событие для обновления небольших данных, принадлежащих определенному компоненту. Текущая реализация шины событий не дает информации об узле назначения или источнике (я видел _uid каждого компонента, может быть, мы можем использовать этот уникальный _uid для проводки событий?), Поэтому vuejs2.0 не может фактически поддерживать двухточечную передачу событий . Если быть точным, шина событий vuejs2.0 поддерживает только связь типа компонента с типом компонента? Есть ли простое решение для удовлетворения этого требования: запускается событием в дереве и обновляет СВОИ СОБСТВЕННЫЕ ДАННЫЕ?
vuex отлично подходит для управления данными глобального статического состояния на уровне приложения, но, насколько я понимаю, он может не подходить для управления данными конкретных локальных компонентов?
Приветствуются дополнительные размышления по этому вопросу.

@cnweibo Я ответил на ваш вопрос примером на форуме. Думаю, этот пример удовлетворит ваши потребности.
http://forum.vuejs.org/topic/4832/vue2-0-event-bus-issue-how-to-deliver-event-to-parent-when-the-same-multiple-parent-children-in- дом / 6

Есть ли простое решение для удовлетворения этого требования: запускается
событие в дереве и обновить ЕГО СОБСТВЕННЫЕ ДАННЫЕ

Это решается простым vuex, без сложной системы событий.

vuex отлично подходит для управления данными глобального статического состояния на уровне приложения,
но, насколько я понимаю, это может не подходить для конкретных локальных данных компонента
управление

«местный» означает только один компонент. Ваш вариант использования - управление состоянием через
несколько компонентов, поэтому его глобальный.
И vuex может иметь модули (поддеревья состояний), поэтому это не `` глобальная переменная ''
своего рода «глобальный». Вы можете управлять группами компонентов с их собственным vuex
модули.

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

В чт, 1 сентября 2016 г., 16:17 cnweibo [email protected] написал:

@posva https://github.com/posva , спасибо за информацию. автобус
концентратор действительно хорошо работает в простых однокомпонентных точках на один компонент
точечная связь. Если есть несколько компонентов с одним и тем же компонентом
типа, будет проблема, к сожалению, это нормальный случай. Много
случаях, я хочу использовать событие для обновления небольших данных, принадлежащих некоторым
конкретный компонент. Текущая реализация шины событий не дает
информация о пункте назначения или узле отправления (я видел _uid каждого
компонент, может быть, мы можем использовать этот уникальный _uid для проводки событий? ), так
Фактически vuejs2.0 не поддерживает двухточечную передачу событий. Быть
точно, шина событий vuejs2.0 поддерживает только тип компонента для типа компонента
коммуникация? Есть ли простое решение для выполнения этого требования:
запускается событием в дереве и обновляет _ЕГО СОБСТВЕННЫЕ ДАННЫЕ_
vuex отлично подходит для управления данными глобального статического состояния на уровне приложения,
но, насколько я понимаю, это может не подходить для конкретных локальных данных компонента
управление?

Приветствуются дополнительные размышления по этому вопросу.

-
Вы получаете это, потому что подписаны на эту ветку.
Ответьте на это письмо напрямую, просмотрите его на GitHub
https://github.com/vuejs/vue/issues/3581#issuecomment -244008699 или отключить звук
нить
https://github.com/notifications/unsubscribe-auth/AFTLl1bjHqWTVDAkr8Fqbx0WiTuH16n2ks5qlooBgaJpZM4JyUfJ
.

Сейчас я закрою этот вопрос, потому что

  1. Были предоставлены решения и
  2. В любом случае, проблемы с Github - не лучшее место для обращения за поддержкой (см. Руководство)

@ktsn , спасибо за вашу демонстрационную скрипку. Это именно то, что мне нужно, простое решение!
@fnlctrl , я потрачу больше времени на так называемое модульное управление состоянием vuex

еще раз спасибо ~!

На мой взгляд $ broadcast не нужен, только падающий реквизит data-flow.
Любой $ dispatch можно переопределить как одноуровневый v-on и $ emit следующим образом (в Vue 1):
<child-component @select="$emit('select', $arguments[0])" /> по каждому задействованному компоненту
В любой другой ситуации следует использовать автобусы для специальных мероприятий.

На самом деле, v-on на теге компонента для настраиваемого события на самом компоненте также работает с $ emit из самого компонента.

@cnweibo Для записи можно получить данные о событии.

{
  template: `<foo @bar="dosomething">`,
  methods: {
    dosomething(params1, params2, ... and all the event data args) {}
  }
}

Но данные события не могут быть получены в vuejs2.0

Конечно, может, что заставляет вас думать иначе?

@fnlctrl
@LinusBorg
Извините, у меня недопонимание, и я кое-что не прояснил. в предоставленном шаблоне @fnlctrl действительно может получить все данные в своем обработчике событий даже с

 <comp @some-event-emitted-by-comp-internal-template="someFuncInParentScope"></comp>

Скопируйте / вставьте мой собственный комментарий из другого выпуска: https://github.com/vuejs/vue/issues/2760#issuecomment -250883407

Я думаю, что удаление $ dispatch было ужасной идеей. Это был не первый фреймворк / библиотека пользовательского интерфейса, реализующая понятие всплывающих действий / событий вверх по визуальному дереву. Это хорошо зарекомендовавшая себя идея. Зачем убирать эту функциональность на том основании, что «возможность отправлять событие, вызывающее побочные эффекты в его неизвестном родительском дереве, звучит для меня как рецепт неприятностей»? Вы должны оставить эту ответственность пользователям. Я уверен, что у большинства хватит здравого смысла использовать эту функцию должным образом. Это не новая концепция!

Я действительно не вижу пользы от этого изменения, когда эта библиотека построена на давно устоявшихся веб-технологиях / концепциях, таких как события DOM и DOM, которые на самом деле пузыри визуального дерева и делали это в течение многих лет ни с кем. жалуясь. Разве идея компонентов не была принята недавно благодаря предложению W3C для веб-компонентов? На мой взгляд, имеет смысл только то, что компоненты Vue ведут себя аналогично обычным элементам DOM в отношении того, как выполняется обработка событий.

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

Другие предложения в этой ветке напоминают мне о том, как EmberJS хочет это сделать. Передача закрывающих действий в качестве свойств компонентам на каждом уровне иерархии. Так утомительно и ненужно! Vuejs был причиной того, что я написал https://www.npmjs.com/package/ember-component-action-bubbling!

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

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

Скажем, у вас есть приложение, в котором пользователь может войти в систему. Решение на основе событий:

  1. Слушайте событие входа в систему
  2. Позже запустите событие, указав имя пользователя и пароль.
  3. Реагируйте на указанное событие соответствующим образом в любых компонентах, которые слушают

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

Итак, давайте использовать подход с отслеживанием состояния:

  1. Создайте глобальную переменную состояния, представляющую информацию об учетной записи пользователя. Это null при выходе из системы и информация для входа пользователя при входе в систему.
  2. Когда пользователь входит в систему, установите информацию об учетной записи.

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

Декларативный подход позволяет вам писать компоненты таким образом, чтобы они всегда выглядели одинаково, в зависимости от локального / глобального состояния, независимо от того, что пользователь делает в вашем приложении, без необходимости слушать, что происходит. Я считаю, что Vue предназначался для этого все время, но, как и в большинстве случаев в разработке программного обеспечения, нам потребовалось время, чтобы понять это. Но я чертовски рад, что мы это сделали.

РЕДАКТИРОВАТЬ: О, и не забывайте, что вы можете следить за параметрами и, скажем, отправлять запрос AJAX или выполнять какое-либо другое действие при его изменении. например, после того, как пользователь войдет в систему, посмотрите переменную loggedIn, если она истинна, загрузите изображения их профилей или что-то в этом роде.

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

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

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

Итак, теперь, с удалением $ dispatch, вам нужно, чтобы компонент кнопки знал о каком-то глобальном объекте, который управляет пользовательским сеансом приложения, и напрямую уведомлял его о намерении. Это делает кнопку тесно связанной со всем вашим приложением.

Или у вас может быть кнопка, вложенная на 10 уровней в глубину, и вам нужно будет объявить обработчик v-on:login на каждом уровне, чтобы намерение достигло своего предназначения. Совершенно ненужно.

На самом деле, необходимость делать v-on на каждом уровне только усложняет сопровождение вашего кода.

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

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

Кнопка входа была просто примером. И хранилище vuex - это то, о чем я имел в виду, когда упоминал «некий глобальный объект». Мне нужно было бы изучить, как работает vuex, но я ожидаю, что вы сильно привязываете какой-то случайный компонент к остальной части состояния вашего приложения, просто имея необходимость управлять ссылкой на магазин.

Это нежелательно, если, например, кнопка входа была частью какой-то сторонней библиотеки.

Я действительно просто хочу, чтобы вы не отказались от * _choice * _ для использования любой из парадигм, особенно когда всплытие событий широко признано и, следовательно, его легко понять для новых участников проекта.

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

Поскольку данные в приложении Vue идут сверху вниз, вы хотите сохранить как можно большую часть вашего локального состояния как можно более высокоуровневым. Само по себе глубокое вложение - это проблема, которую следует избегать как можно больше. Распространять события на два уровня ниже - не так уж и сложно, но есть вероятность, что вам может потребоваться переосмыслить структуру шаблона, если она идет глубже.

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

В 9 случаях из 10 не должно быть никаких логических причин для доступа к магазину из-за использования свойств и событий.

Совершенно моя точка зрения.

Сама по себе глубокая вложенность - это проблема, которую следует избегать как можно больше.

Иногда это не вариант.

Не так уж и сложно распространять события на два уровня ниже.

Не совсем так, когда эти уровни уходят глубже.

более простые для понимания парадигмы - это те, которые в конечном итоге подвергаются жестокому обращению до конца ада и становятся громоздкими

Это должно зависеть от дисциплины ваших пользователей.

Вы можете продолжить использовать 1.0 или перейти на другую платформу, если такой подход вам не нравится.

Ммк.

Простота и удобство - вот причина, по которой я подумывал о переходе с Ember на Vue. $dispatch - одна из тех вещей, которые мне нравились в Vue, и мне кажется, что его удаление произвольно.

Команда удалила множество функций из версии 2.0. Я честно согласен со всеми ними. Только не этот.

Спасибо за ваши ответы.

@ktsn Альтернативы $ broadcast и $ dispatch очень просты, это удаление улучшилось и улучшилось.

@rhyek Я хотел бы высказать свое мнение о паре поднятых вами вопросов. Поскольку обсуждение уже коснулось ряда тем, я хотел бы вернуться к основам того, почему мы устарели $ diospatch и $ broacast:

1. неявная связь.

Если у вас есть родитель и глубоко вложенный дочерний элемент, который отправляет событие, нет никакого способа вывести эту взаимосвязь из кода (и то же самое верно для $broadcast , очевидно.)

Если вы посмотрите на другие изменения и устаревания, которые мы представили в Vue 2.0, вы можете понять, что удаление неявного поведения в пользу явных альтернатив является общей темой, и отказ от $dispatch подходит как раз для этого.

Пример:

// parent
events: {
  'some-event': function () { ... }
}

// deeply nested child:
$dispatch('some-event')

Это нормально, когда у родителя есть только один прямой потомок, но в этом случае $emit() со слушателем в шаблоне тоже не является реальной дополнительной работой.

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

Вы говорите, что вам нравятся $ dispatch и $ broadcast, потому что вам не нужно передавать их через другие компоненты. И я могу согласиться с тем, что это проще - но мы не сталкивались со многими ситуациями, когда это было действительно необходимо, или, скорее, если бы существовала такая цепочка пропуска события, скорее всего, данные были бы изменены / добавлено / во время этой поездки компонентом между ними.

2. Названия событий

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

// parent
events: {
  'close': function () { ... }
}

// deeply nested child 1:
$dispatch('close')
// deeply nested child 2:
$dispatch('close')

..и если эти дети являются сторонними библиотеками, вы сейчас облажались. или вам нужно поймать событие в каком-то компоненте посередине, чтобы просто переименовать его, прежде чем вы $dispatch() дальше до родителя. И не забудьте прокомментировать это, потому что кто-то, глядя на этот код, может подумать, почему вы не делаете ничего другого с событием, кроме его переименования.

Использование слушателей $ emit и шаблонов не вызывает этой проблемы. вы можете везде использовать простые короткие имена событий, они не будут конфликтовать друг с другом, поскольку каждое событие имеет собственный обратный вызов, прикрепленный к шаблону @close="callback ".

Я просто хочу, чтобы вы не отказались от * выбора * для использования любой парадигмы,

Если бы мы думали, что обе парадигмы могут работать одинаково хорошо, мы бы относились к ним одинаково. Но мы так не думаем по указанным выше и другим причинам.

Поэтому мы стараемся подтолкнуть пользователей к методам, которые, по нашему мнению, работают лучше всего, и при этом оставляем способ обойти это с помощью метода «глобальной шины».

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

Может быть, вы можете привести пример, в котором, по вашему мнению, вам лучше всего подходят $ dispatch и $ broadcast, и я пытаюсь показать вам, как «наш» подход может улучшить ситуацию?

Я думаю, что $ dispatch / $ broadcast и event bus обращаются к разным вещам. Они могут упростить сопровождение кода и сделать его независимым от различных сценариев. Если мы сможем удержать их обоих, это будет здорово.
Трудно сказать, что один лучше другого во всех случаях.

@cnweibo Я думаю, что с обеих сторон были довольно исчерпывающие аргументы, и, честно говоря, я не вижу вашей точки зрения на то, чтобы «решать разные вопросы». Не стесняйтесь приводить дополнительные аргументы, но я могу сказать вам, что этого не произойдет.

Если вы действительно этого хотите, не так уж сложно реализовать его самостоятельно в виде плагина.

@LinusBorg Я действительно ценю время, которое вы

Вы говорите, что вам нравятся $ dispatch и $ broadcast

Честно говоря, мне просто нравится $dispatch . $broadcast определенно показался мне странным. Как я уже сказал, $dispatch - это просто всплывающее сообщение о событиях, которое на данный момент широко распространено среди многих платформ. $broadcast ... не так уж и много. Единственное, с чем я когда-либо сталкивался, - это события «предварительного просмотра» в WPF, которые связаны с обычными событиями. Они «туннелируют» вниз по визуальному дереву от самого верхнего элемента к источнику исходного события, но они отправляются только вниз по цепочке связанных элементов и не распространяются на все.

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

Я согласен с этим, и в любом случае я обычно этим занимаюсь. Это также то, что люди привыкли делать в jQuery. Более того, некоторые платформы просто отправляют объект «источник» в качестве аргумента обработчику, и вы можете фильтровать контексты на основе этого (подсказка: instanceof ). Например, для событий DOM доступно event.target . Другие платформы имеют преимущество работы со статическими типами, поэтому с этим «конфликтом» довольно сложно столкнуться (событие - это экземпляр класса).

В любом случае, честно говоря, я просто не понимаю, почему это так беспокоит команду VueJS. Если люди не могут быть достаточно осторожными при использовании $dispatch , я уверен, что вы можете найти много других вещей, которые они делают неправильно, используя вашу библиотеку. Насколько далеко вы пойдете, чтобы «защитить» своих пользователей от беспечности?

Это нормально, когда у родителя есть только один прямой потомок, но в этом случае $ emit () со слушателем в шаблоне тоже не является реальной дополнительной работой ..

Честный вопрос (поскольку я определенно новичок в Vue), помимо объявления слушателей на каждом уровне, разве вам также не нужно $emit событие для каждого компонента в цепочке? Это так раздражает.

В заключение позвольте мне процитировать то, что кто-то сказал по проблеме на vue-cli о введении «официальных шаблонов» для новых проектов (https://github.com/vuejs/vue-cli/issues/123#issuecomment-233071630):

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

Думаю, в конце концов, это всего лишь метр баланса. Сколько из этих решений мы можем принять заранее для всех (большинства) наших пользователей и сколько или какие из них пользователи хотят сделать самостоятельно.

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

Если вы действительно этого хотите, не так уж сложно реализовать его самостоятельно в виде плагина.

@ yyx990803 Это, вероятно, то, чем я буду заниматься в конечном итоге ... вероятно.

@LinusBorg также:

Поэтому мы стараемся подтолкнуть пользователей к методам, которые, по нашему мнению, работают лучше всего, и при этом оставляем способ обойти это с помощью метода «глобальной шины».

Вы не «пытаетесь управлять», вы принуждаете. :)

Вы пробовали реализовать одну и ту же функцию с методами dispatch и EventBus?
Это может помочь

@posva Я планирую это сделать, но я имею в виду, что вы в основном объявляете объект шины событий в каком-то модуле и импортируете его куда угодно в $emit , нет? Мне это не нравится, черт возьми. Я определенно использую его для некоторых вещей, но я твердо уверен, что это не то, чем я хочу заниматься каждый раз.

В любом случае, честно говоря, я просто не понимаю, почему это так беспокоит команду VueJS. Если люди не могут быть достаточно осторожными при использовании $dispatch ,

Дело в том, что никто в команде не мог указать на реальный вариант использования $dispatch() в котором он был бы предпочтительнее других решений (не только $emit() , но и автобус, или global state), и мы не увидели ни одного сообщения в бесчисленных сообщениях на форуме, на которые мы ответили.

Это может быть субъективное мнение, но, возможно, вы поймете, что если вся команда думает, что «это, по нашему опыту, всегда худшее решение», мы отбрасываем его из ядра.

Здесь я хочу возобновить свое предложение обсудить реальный пример.

Я уверен, что вы можете найти много других вещей, которые они делают неправильно, используя вашу библиотеку. Насколько далеко вы пойдете, чтобы «защитить» своих пользователей от беспечности?

Это, конечно, деликатный вопрос, и его трудно найти. Придется судить по каждому делу.

Это нормально, когда у родителя есть только один прямой потомок, но в этом случае $ emit () со слушателем в шаблоне тоже не является реальной дополнительной работой ..

Честный вопрос (поскольку я определенно новичок в Vue), помимо объявления слушателей на каждом уровне, разве вам не нужно также генерировать событие $ emit для каждого компонента в цепочке? Это так раздражает.

Поскольку я говорю о прямом освобождении родитель-потомок, вам нужно будет выполнить $ emit () только один раз.

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

Поэтому мы стараемся подтолкнуть пользователей к методам, которые, по нашему мнению, работают лучше всего, и при этом оставляем способ обойти это с помощью метода «глобальной шины».

Вы не «пытаетесь управлять», вы принуждаете. :)

Я бы сказал, что мы сделаем вашу жизнь немного сложнее - вы можете

  • использовать шину, что не одно и то же, но в большинстве случаев можно добиться аналогичного поведения.
  • повторно реализовать это как плагин довольно легко.

Мы не заставляем вас использовать $emit() , мы просто немного усложняем задачу.

Я думаю, вы также можете добавить его в каждый экземпляр Vue: Vue.prototype.$bus = new Vue()
Не любить что-то не очень конструктивно ...
Буду ждать ваших примеров 😄

@posva

Думаю, вы также можете добавить его в каждый экземпляр Vue: Vue.prototype. $ Bus = new Vue ()

Мне нравится, что. Довольно умно.

Не любить что-то не очень конструктивно

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

Буду ждать ваших примеров 😄

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

Я, конечно, шучу над последним комментарием. Как я уже говорил ранее, я вижу их применение и обязательно найду проблему, которую можно решить с их помощью. Фактически, в некоторых проектах, над которыми я работал с использованием Ember, я обычно пишу «сервис», который действует точно так же, как глобальный менеджер состояний. Уверяю вас, я не намеренно пытаюсь быть упрямым.

Мне очень нравится Vue. Я просто хочу _любить_ это, понимаете?

разве вам также не нужно генерировать событие $ emit для каждого компонента

Да, если вы думаете о пузырях событий. И нет, если вы используете компонентный состав.

Например:

<div>
  <a-button @click="modalShown = true">Open modal</a-button>
  <a-modal v-if="modalShown">
    <a-button @click="modalShown = false">Close modal</a-button>
  </a-modal>
</div>

Компоненту a-modal не нужно заботиться о событиях компонента a-button , потому что оба экземпляра a-modal и два экземпляра a-button являются «прямыми логическими дочерними элементами» одного экземпляра. , несмотря на сложную иерархию представлений с вложением.

Думаю, сейчас я просто повторяюсь. Я как-нибудь постараюсь обойти эту проблему. Мне просто кажется странным, что это обсуждение вращается вокруг определения нескольких обходных путей для чего-то довольно стандартного и практичного, чего просто больше не существует по какой-либо причине.

@LinusBorg :

Дело в том, что никто в команде не мог указать на реальный вариант использования $ dispatch (), в котором он был бы предпочтительнее других решений (не только $ emit ()

Для меня это звучит так, будто инженер-строитель спрашивает меня, почему нельзя перекрывать съезд с шоссе:

Он говорит что-то вроде: «Этот съезд ведет к перекрестку, где люди не понимают, повернуть налево или направо. Большинство людей знают дорогу, потому что живут здесь много лет, но новые граждане часто теряются на пару дней. минут, и мы хотим этого избежать ".

Я говорю: «Хорошо, конечно, можешь закрыть, это круто. Мне просто нужно проехать 10 км до следующего съезда. Я справлюсь».

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

Для меня это звучит так, будто инженер-строитель спрашивает меня, почему нельзя перекрывать съезд с шоссе:

Он говорит что-то вроде: «Этот съезд ведет к перекрестку, где люди не понимают, повернуть налево или направо. Большинство людей знают дорогу, потому что живут здесь много лет, но новые граждане часто теряются на пару дней. минут, и мы хотим этого избежать ".

Я тоже добавлю свой плохой метафор. :) На мой взгляд, это больше похоже на:

  • «Эта дорога побуждает людей мчаться быстрее, чем они должны. На ограничения скорости редко обращают внимание. Мы должны добавить некоторые бамперы, чтобы заставить людей замедляться».
  • «Но я люблю быстро добраться до пункта назначения, превысив скорость!»
  • «Конечно, несколько раз он может хорошо вас обслужить, но мы постоянно наблюдаем этот участок дороги более 1,5 лет, и количество аварий и людей, пропускающих следующий съезд, просто не стоит того, как многие водители, которые прошли одна из этих проблем засвидетельствована ".
  • «Но мне не нравятся эти бамперы!»
  • Что ж, для 99% направлений эта другая дорога такая же быстрая, как и эта до бамперов, просто возьмите эту.
  • «Но мне не нравится эта другая дорога! Вид не такой красивый!»
  • ...

Не любить что-то не очень конструктивно

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

Я думаю, что @posva имела в виду: «Мне это нравится» не является конструктивным аргументом при обсуждении того, чтобы мы либо оставляли что-то, либо добавляли что-то в библиотеку с широким кругом пользователей. Вот почему я все время прошу обсудить реальный вариант использования, а не личные предпочтения.

Да, за исключением того, что вы взорвали прекрасное шоссе и построили другое с прорезиненным асфальтом, потому что где-то читали, что это довольно аккуратно. Кроме того, это лишние 10 км. :)

О примере: я думаю, что ответ на исходный вопрос о рекурсивных компонентах - это нормально. Только представьте, что вы хотите что-то делать на каждом уровне последовательно, когда событие обнаруживается, и у вас есть отличный пример. Сделать это с помощью $ dispatch довольно просто.

Вы хотите увидеть код?

Да, пожалуйста

@posva Я привел пример по предыдущему комментарию. Примечание: если вам нужно больше нескольких секунд подумать, как это сделать без $ dispatch, это подтверждает мою точку зрения.

О примере: я думаю, что ответ на исходный вопрос о рекурсивных компонентах - это нормально. Только представьте, что вы хотите что-то делать на каждом уровне последовательно, когда событие обнаруживается, и у вас есть отличный пример. Сделать это с помощью $ dispatch довольно просто.

с $dispatch()

// recursive-child
<template>
  <recursive-child></recursive-child>
  <button @click="dispatch">Do something</button>
<template>

<script>
  export default{
    methods: {
      dispatch() { this.$dispatch('do-something') }
    },
    events: {
      'do-something': function () { 
         // do something, or don't
         return true // nessessary to make the event bubble up further. Don't like the un-expressivness of this
       }
    }
  }
</script>

с $emit()

// recursive-child
<template>
  <recursive-child @do-something="doSomething"></recursive-child>
  <button @click="doSometing">Do something</button>
<template>

<script>
  export default{
    methods: {
      doSomething() {
        // do someting, or don't
        this.$emit('do-something')
      }
    }
  }
</script>

Это действительно хуже?

Есть еще один? :)

Да конечно. Что, если они не рекурсивны, но все еще так вложены?

Хорошо. Здесь 5 утра, и благодаря тебе у меня будет тяжелый день. Если потом придумаю что-то получше, выложу, если нет, то либо ты выиграл, либо я потерял интерес :)

Что, если они не рекурсивны, но все еще так вложены?

Вам нужно будет добавить слушателя @event= в каждый шаблон для $emit() , а не для $dispatch() , вот и все.

Это можно рассматривать как хорошее или плохое, в зависимости от того, подчеркиваете ли вы многословность или выразительность.

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

<child-comp @event="$emit('event', $arguments)>
  • Вы будете оплакивать «связь» между компонентами.
  • Похвалю выразительность
  • Кроме того, это немного больше для набора текста, но не имеет большого значения.
  • и я по-прежнему утверждаю, что на примере реального варианта использования, вероятно, доступна другая оптимизация, например, глобальное хранилище, но это зависит от отдельного сценария, и с примером кода трудно спорить.

В любом случае, приятного обсуждения, наслаждайтесь заслуженным сном.

@rhyek, это похоже на обходные пути только потому, что вы в первую очередь решили использовать $dispatch , но это не цель. Цель состоит в том, чтобы позволить компонентам обмениваться данными друг с другом с приличной ремонтопригодностью. При достижении этой цели $dispatch является худшим решением, если вы перечисляете все практические плюсы и минусы, исключая предпочтения, поэтому мы отказались от него.

Также обратите внимание, что всплытие событий DOM принципиально отличается от межкомпонентного взаимодействия. Аргумент, что «всплытие событий широко признано», не означает, что это должно быть хорошее решение проблемы, которую мы пытаемся решить.

Я закончил комментировать эту ветку, потому что мне трудно спорить с «мне это просто не нравится».

Была ли эта страница полезной?
0 / 5 - 0 рейтинги