Vue: vuejs2.0は$ broadcast、$ dispatchイベントAPIを保持する必要がありますか? 2.0でポイントツーポイントの親子コミュニケーションに対処するための良い解決策はありません

作成日 2016ĺš´09月01日  Âˇ  41コメント  Âˇ  ソース: vuejs/vue

@ yyx990803 、
こんにちは、vuejsコアチーム、
vuejs2.0を使用した親子コンポーネント間のポイントツーポイント通信の適切なソリューションを見つけるのに苦労しています。
vuejs2.0は$ broadcast、$ dispatch apiを廃止したため、$ Broadcast、$ dispatchがvuejs2.0イベントバス機能を提供する代替ソリューションを見つけるのは非常に困難です。
このトピックに関するスレッドをここに書いたので、ここに貼り付けてさらに議論したいと思います。

vuejs2.0に関する優れたアイデアや解決策がない限り、閉じないでください。

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

上記のコードでは、たとえば、pcom1の子が、soncoma $ emitイベントを送信する場合、次のようになります。

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

pcomでは、そのイベントを次のように聞きます。

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

pcom1だけがそのイベントを処理するようにしたいのですが、残念ながらpcom2もそれを処理します。
この状態に取り組む方法は?

私のアプリケーションの回避策の1つは、this。$ parentをイベントバスとして使用することです。
子供の場合:

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>

recursivechildはどのように直接のpcomコンポーネントと通信しますか?
これらのトピックについて、あなたの考えやポイントを教えてください。
ありがとう〜!

discussion

最も参考になるコメント

@rhyekあなたが提起したいくつかのポイントについて私の2ctを与えたいと思います。 議論はすでに多くのトピックをブラッシュアップしているので、$ diospatchと$ broacastを非推奨にした理由についての基本に戻りたいと思います。

1.暗黙の結合。

イベントをディスパッチする親と深くネストされた子がある場合、コードからこの関係を推測する方法はありません(もちろん、 $broadcastについても同じことが言えます)。

Vue 2.0で導入した他の変更と非推奨を見ると、明示的な代替手段を優先して暗黙的な動作を削除することが一般的なテーマであり、 $dispatch非推奨がそこにぴったりであることに気付くかもしれません。

例:

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

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

これは、親に直接の子が1つしかない場合は問題ありませんが、その場合、テンプレートにリスナーを含む$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も、兄弟コンポーネント間の通信を解決しません。 代わりに、 Node.jsの

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- dom / 6

その要件に対処するための簡単な解決策はありますか?
ツリー内のイベントとその独自のデータを更新します

これは、複雑なイベントシステムを使用せずに、単純にvuexで解決されます。

vuexは、アプリケーションレベルのグローバル静的状態データ管理に最適です。
しかし、私が理解しているように、特定のローカルコンポーネントデータには適していない可能性があります
管理

「ローカル」は、単一のコンポーネントのみを意味します。 あなたのユースケースは、全体の状態を管理しています
複数のコンポーネントなので、そのグローバル。
また、vuexはモジュール(状態サブツリー)を持つことができるため、「グローバル変数」ではありません。
一種の「グローバル」。 独自のvuexを使用してコンポーネントのグループを駆動できます
モジュール。

この「イベント対共有状態」の議論全体は数ヶ月で解決されました
以前、結論は、グローバルイベントバスまたはvuexのいずれかを使用することです。 だから私は
vuexとその仕組みについてもっと読むことをお勧めします。

木、2016ĺš´9月1日には、16時17分cnweibo [email protected]は書きました:

@posva https://github.com/posva 、情報ありがとうございます。 バス
ハブは、単一のコンポーネントを指す単純な単一のコンポーネントで実際にうまく機能します
ポイント通信。 同じコンポーネントを持つコンポーネントが複数ある場合
タイプ、問題が発生しますが、残念ながら、これは正常なケースです。 多くの
場合によっては、イベントを使用したいのは、いくつかに属する小さなデータを更新することです
特定のコンポーネント。 現在のイベントバスの実装では
宛先または発信ノードに関する情報(私はすべての_uidを見てきました
コンポーネント、イベントの配線にこの一意の_uidを使用できるでしょうか? )、 それで
vuejs2.0は、実際にはポイントツーポイントイベント通信をサポートできません。 することが
正確なvuejs2.0イベントバスは、コンポーネントタイプからコンポーネントタイプのみをサポートします
コミュニケーション? その要件に対処するための簡単な解決策はありますか?
ツリー内のイベントによってトリガーされ、_ITS OWNDATA_を更新します
vuexは、アプリケーションレベルのグローバル静的状態データ管理に最適です。
しかし、私が理解しているように、特定のローカルコンポーネントデータには適していない可能性があります
管理?

この問題についてもっと考えてみてください。

—
このスレッドにサブスクライブしているため、これを受け取っています。
このメールに直接返信し、GitHubで表示してください
https://github.com/vuejs/vue/issues/3581#issuecomment -244008699、またはミュート
スレッド
https://github.com/notifications/unsubscribe-auth/AFTLl1bjHqWTVDAkr8Fqbx0WiTuH16n2ks5qlooBgaJpZM4JyUfJ
。

この問題を解決します。

  1. ソリューションが提供され、
  2. Githubの問題は、とにかくサポートを求めるのに適切な場所ではありません(ガイドラインを参照)

@ktsn 、デモフィドルをありがとう。 それはまさに私が簡単な解決策を望んでいることです!
@fnlctrl 、いわゆるモジュラーvuex状態管理により多くの時間を費やします

よろしくお願いします〜!

私の意見では、$ roadcastは必要ありません。落下する小道具のデータフローのみが必要です。
$ 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 :

$ dispatchを削除するのはひどい考えだったと思います。 これは、ビジュアルツリー上でバブリングアクション/イベントの概念を実装した最初のUIフレームワーク/ライブラリではありませんでした。 それは十分に確立された考えです。 「未知の親ツリーで副作用を引き起こすイベントをディスパッチできることは、私にとってトラブルのレシピのように聞こえる」という前提で、なぜこの機能を取り除くのですか? この責任はユーザーに任せる必要があります。 この機能を適切に使用することは、ほとんどの常識があると思います。 それは新しい概念ではありません!

このライブラリが、DOMやDOMイベントなどの長年確立されたWebテクノロジー/概念に基づいて構築されている場合、この変更のメリットは実際にはわかりません。実際には、ビジュアルツリーをバブルアップし、誰もいない状態で何年もそうしています。文句を言う。 コンポーネントのアイデアは、Webコンポーネントに関するW3Cの提案のおかげで、最近受け入れられたものではありませんか? 私の意見では、イベント処理がどのように行われるかに関して、Vueコンポーネントが通常のDOM要素と同様に動作することだけが理にかなっています。

グローバルイベントバスを使用するために提案された代替案は、(長年にわたって確立された概念であるため)より実用的で効果的で理解しやすいものがすでに存在する場合、私には非論理的です。

このスレッドの他の提案は、EmberJSがそれをどのように実行したいかを思い出させます。 階層の各レベルのコンポーネントにプロパティとしてクロージャアクションを渡します。 とても退屈で不必要です! Vuejsが私がhttps://www.npmjs.com/package/ember-component-action-bubblingを書いた理由でした

これとは別に、私はあなたの図書館が本当に好きです。 しかし、真剣に、これはひどい変化だったと思います。

イベントバスパラダイムは、イベントベースのアーキテクチャが宣言型の状態ベースのアーキテクチャよりも劣ることが多い場合に、まったく同じことを行うためのソリューションとしてのみ提案されました。

たとえば、ユーザーがログインできるアプリがあるとします。イベントベースのソリューションでは、次のようになります。

  1. ログインイベントを聞く
  2. 後でユーザー名とパスワードを使用してイベントを発生させます
  3. どのコンポーネントがリッスンしていても、それに応じて上記のイベントに応答します

ただし、これにはいくつかの問題があります。 最大の問題は、イベントが発生したときにDOMでレンダリングされないコンポーネントが変更を受け取らないことと、アプリケーションのどの部分がイベントを受け取るかがまったくわからないことです。 さらに、イベントの受信者は、追加情報が提供されない限り、イベントがどこから来ているのかを知ることはできません。 申し訳ありませんが、それは私が扱ってきた大規模なクラスターファックであり、再び使用する必要はありません。

それでは、ステートフルアプローチを使用しましょう。

  1. ユーザーアカウント情報を表すグローバル状態変数を作成します。 サインアウトするとnull 、サインインするとユーザーのログイン情報が表示されます。
  2. ユーザーがログインしたら、アカウント情報を設定します。

この状態変数に依存するアプリ内のすべてがそれに応じて更新されます。 イベントはありません。コンポーネントは常に正しい情報を表示するため、コンポーネントがいつどこで作成されたかは関係ありません。 イベントを使用してグローバル状態を更新することもできますが、更新できるのになぜそうするのでしょうか。

宣言型アプローチを使用すると、ユーザーがアプリケーションで何をしているかに関係なく、ローカル/グローバル状態に正確に応じて常に同じように表示されるようにコンポーネントを記述できます。 これがVueの意味であると私は信じていますが、ソフトウェア開発のほとんどのことと同様に、それを理解するのにしばらく時間がかかりました。 しかし、私たちがやったことをとてもうれしく思います。

編集:ああ、パラメータを監視して、たとえばAJAXリクエストを送信したり、変更されたときに他のアクションを実行したりできることを忘れないでください。 たとえば、ユーザーがログインした後、「loggedIn」変数を監視し、それがtrueの場合は、プロフィール画像などを読み込みます。

私はあなたが言っていることを理解していますが、いくつかのランダムなコンポーネントがグローバル状態を変更することは、そのランダムなコンポーネントがイベントをバブルアップさせることと同じことは、どこにあるかを知っていると思います。 それでも、アプリケーションのフローが誤って「ダーティ」になるというまったく同じリスクがあります。

両方のパラダイムをクリーンな方法で処理する方法があり、それは通常、フレームワークのユーザーの責任であることになります(そしてそうすべきです)。

1つのメカニズムが他のメカニズムよりも理にかなっている特定の状況があります。 たとえば、ログイン状態はアプリケーション全体に知られているものでなければならないことに同意します。グローバル状態は理にかなっています。 ただし、アプリケーションユーザーがクリックするボタンは、通常、実際にユーザーをログインさせる背後にあるロジックを処理しません。これは、チェーンの上位で処理されるものになります。 それはコンポーネントかもしれませんし、ルートかもしれません。 ボタンは、おそらく唯一のログインに意思のようなものを通知する必要があります。ボタンは、それゆえ、直接あなたのグローバルな状態を変更する必要がありません。

そのため、$ dispatchが削除されたことで、ボタンコンポーネントが、アプリケーションのユーザーセッションを管理するグローバルオブジェクトを認識し、その意図を直接通知する必要があります。 これにより、ボタンがアプリケーション全体に緊密に結合されます。

または、ボタンを10レベルの深さでネストし、インテントがその運命に到達するように、すべてのレベルでv-on:loginハンドラーを宣言する必要がある場合があります。 全く不要です。

実際、すべてのレベルでv-onを実行する必要があると、コードの保守が難しくなります。

明らかに、状態を直接変更するだけでも問題が発生する可能性がありますが、Vuexは突然変異とアクションでその問題を解決します。 そして、いくつかの解決策が他の解決策よりも法案にうまく適合することは事実ですが、宣言型ロジックがより良い選択肢ではなかったという状況に遭遇したことはありません。

あなたの特定のケースでは、私はおそらくログイン専用のボタンを作らないでしょうね。 補遺では、ログイン関連のコンポーネントが何らかの理由でその深さまでネストされている場合は、グローバル状態を変更するだけです。

ログインボタンはほんの一例です。 そして、vuexストアは、私が「グローバルオブジェクト」について言及したときに言及していたものです。 vuexがどのように機能するかを調べる必要がありますが、ストアへの参照を管理するだけで、ランダムなコンポーネントをアプリの残りの状態に緊密に結合していると思います。

たとえば、ログインボタンがサードパーティのライブラリの一部であった場合、これは望ましくありません。

特にイベントのバブリングが広く認識されているため、プロジェクトの新しい貢献者が簡単に理解できる場合は、どちらのパラダイムを使用する場合でも* _choice * _を取り去らないでください。

たとえば、ルータービューコンポーネントには、ストアにアクセスしてコミットする完全な権限があると思います。これは、「ランダムコンポーネント」の意味によって異なります。 ただし、ボタン、フォーム、その他のUI要素などの再利用用の小さなコンポーネントである場合(10回中9回)、小道具やイベントを使用するよりも、ストアにアクセスする論理的な理由はありません。

Vueアプリケーションのデータはトップダウンであるため、ローカル状態をできるだけトップレベルに保つ必要があります。 深い入れ子自体は、可能な限り避けるべき問題です。 イベントを2レベル下に伝播することはそれほど面倒ではありませんが、それよりも深くなる場合は、テンプレート構造を再考する必要があるかもしれません。

ただし、これはほとんど接線です。 多くの場合、理解しやすいパラダイムは、地獄の終わりまで虐待されて扱いにくくなるパラダイムです。 現在2.0を使用しているほとんどの人が同意しているように、状態ベースのアプローチははるかに簡単です。 1.0を引き続き使用することも、このアプローチが好みでない場合は別のフレームワークに移行することもできます。

10回のうち9回は、小道具やイベントを使用するよりも、ストアにアクセスする論理的な理由はないはずです。

まさに私のポイント。

深い入れ子自体は、可能な限り避けるべき問題です。

場合によっては、これはオプションではありません。

イベントを2レベル下に伝播するのはそれほど面倒ではありません

それらのレベルが深くなると、それほど真実ではありません。

理解しやすいパラダイムは、地獄の終わりまで虐待されて扱いにくくなるパラダイムです。

これは、ユーザーの規律次第です。

1.0を引き続き使用することも、このアプローチが好みでない場合は別のフレームワークに移行することもできます。

Mmk。

シンプルさと便利さが、EmberからVueへの切り替えを検討した理由です。 $dispatchは私がVueについて楽しんだことの1つであり、それを削除することは私にはとても恣意的です。

チームは、2.0リリースの多くの機能を削除しました。 私はそれらすべてに正直に同意します。 これだけではありません。

返信ありがとうございます。

@ktsn $ broadcastと$

@rhyekあなたが提起したいくつかのポイントについて私の2ctを与えたいと思います。 議論はすでに多くのトピックをブラッシュアップしているので、$ diospatchと$ broacastを非推奨にした理由についての基本に戻りたいと思います。

1.暗黙の結合。

イベントをディスパッチする親と深くネストされた子がある場合、コードからこの関係を推測する方法はありません(もちろん、 $broadcastについても同じことが言えます)。

Vue 2.0で導入した他の変更と非推奨を見ると、明示的な代替手段を優先して暗黙的な動作を削除することが一般的なテーマであり、 $dispatch非推奨がそこにぴったりであることに気付くかもしれません。

例:

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

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

これは、親に直接の子が1つしかない場合は問題ありませんが、その場合、テンプレートにリスナーを含む$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とイベントバスは異なることを扱っていると思います。 これらにより、コードの保守が容易になり、さまざまなシナリオで分離できます。 両方を入れておくことができれば素晴らしいです。
いずれの場合も、一方が他方より優れているとは言い難い。

@cnweibo双方でかなり徹底的な議論があったと思いますが、正直なところ、「さまざまなことに取り組む」ことについてのあなたの主張はわかりません。 遠慮なく議論してください、しかし私は確かにこれが起こらないとあなたに言うことができます。

本当に必要な場合は、プラグインとして自分で実装するのはそれほど難しくありません。

@LinusBorg返信を書くのに時間を

あなたは$ dispatchと$ broadcastが好きだと言います

正直、 $dispatch好きです。 $broadcast間違いなく私には奇妙に思えました。 私が言ったように、 $dispatchは単なるイベントのバブリングであり、現時点では多くのプラットフォームに遍在しているものです。 $broadcast ...それほど多くはありません。 私が今までに遭遇したのと似ているのは、通常のイベントとペアになっているWPFの「プレビュー」イベントだけです。 それらは、ビジュアルツリーを最上位の要素から元のイベントのソースまで「トンネリング」しますが、関連する要素のチェーンを直接下って送信されるだけで、すべてに「広がる」わけではありません。

イベントの名前空間を明確にする必要があります

私はそれに同意します、とにかく、それは通常私がすることです。 それは人々がjQueryで行うことに慣れていることでもあります。 さらに、一部のプラットフォームは「ソース」オブジェクトを引数としてハンドラーに送信するだけであり、それに基づいてコンテキストをフィルター処理することもできます(ヒント: instanceof )。 たとえば、DOMイベントではevent.target使用できます。 他のプラットフォームには静的型を処理するという利点があるため、この「衝突」に遭遇するのは非常に困難です(イベントはクラスのインスタンスです)。

いずれにせよ、これがVueJSチームにとってなぜそんなに懸念されるのか私は正直に理解していません。 人々が$dispatch使用に十分注意できない場合は、ライブラリを使用して間違っている他の多くのことを見つけることができると確信しています。 ユーザーを不注意から「保護」するためにどこまで行きますか?

これは、親に直接の子が1つしかない場合は問題ありませんが、その場合、テンプレートにリスナーを含む$ emit()も、実際の余分な作業ではありません。

正直な質問(私は明らかにVueに慣れていないので)、すべてのレベルでリスナーを宣言する以外に、チェーン上のすべてのコンポーネントでイベントを$emitする必要はありませんか? それはとても迷惑な

結論として、新しいプロジェクトに「公式テンプレート」を導入することについて、 vue-cliの問題について誰かが言ったことを引用しましょう(https://github.com/vuejs/vue-cli/issues/123#issuecomment-233071630):

ご存知かもしれませんが、公式テンプレートに縛られているわけではありません。 これはあなたに自由を与えますが、同時にそれはあなたがあなた自身でより多くの決定をする必要を引き起こします。

結局のところ、すべてはほんの1メートルのバランスだと思います。 これらの決定のうち、すべての(ほとんどの)ユーザーに対して事前に行うことができる決定の数と、ユーザーが自分で実行したい数またはどれを決定するか。

私はその哲学に同意しますが、奇妙なことに、この問題について私が遭遇したのと同じ態度ではありません。 そのコメントとここでのコメントの間に私が見るコントラストは、自由に要約されます。 あなたは、良いが、最終的には欠陥のある意図に基づいて選択肢を奪っています。

本当に必要な場合は、プラグインとして自分で実装するのはそれほど難しくありません。

@ yyx990803それはおそらく_私が_やることになることです...おそらく。

@LinusBorgも:

したがって、「グローバルバス」方式で回避する方法を残しながら、ユーザーを最も効果的であることがわかったパクティックに誘導しようとします。

あなたは「操縦しようとしている」のではなく、強制しているのです。 :)

dispatchとEventBusメソッドの両方で同じ機能を実装しようとしましたか?
それは役立つかもしれません

@posva予定していますが、基本的には、あるモジュールでイベントバスオブジェクトを宣言し、それを$emitにしたい場所にインポートします。 私はそれが好きではありません、tbh。 絶対に使うこともありますが、毎回やりたいことではないと強く信じています。

いずれにせよ、これがVueJSチームにとってなぜそんなに懸念されるのか私は正直に理解していません。 $dispatch使用に十分注意できない場合

重要なのは、チームの誰もが$dispatch()実際のユースケースを指摘できず、他のソリューション( $emit()だけでなく、バ​​ス、またはグローバルな状態)、そして私たちが答えたそれについての無数のフォーラムの投稿にも何も見られませんでした。

これは主観的な見方かもしれませんが、チーム全体が「これは私たちの経験では常に劣った解決策である」と考えると、コアから外してしまうことを理解できるかもしれません。

この時点で、実際の例について話し合うためにオファーを更新したいと思います。

あなたは彼らがあなたのライブラリを使って間違っている他の多くのことを見つけることができると確信しています。 ユーザーを不注意から「保護」するためにどこまで行きますか?

もちろん、これは微妙な質問であり、見つけるのが難しいバランスです。 ケースバイケースで判断する必要があります。

これは、親に直接の子が1つしかない場合は問題ありませんが、その場合、テンプレートにリスナーを含む$ emit()も、実際の余分な作業ではありません。

正直な質問(私は明らかにVueに慣れていないので)、すべてのレベルでリスナーを宣言する以外に、チェーン上のすべてのコンポーネントでイベントを$ emitする必要はありませんか? それはとても迷惑なようです。

私は直接の親子関係について話しているので、$ emit()を1回だけ行う必要があります。

深くネストされた子がある場合は、もちろんすべてのレベルで再送信する必要がありますが、繰り返します。ネストされた多くの子にディスパッチすることが本当に必要であるか、他のソリューションよりも望ましい状況は見つかりませんでした。

したがって、「グローバルバス」方式で回避する方法を残しながら、ユーザーを最も効果的であることがわかったパクティックに誘導しようとします。

あなたは「操縦しようとしている」のではなく、強制しているのです。 :)

私たちはあなたの人生を少し難しくすると思います-あなたはできます

  • バスを使用します。これは同じことではありませんが、ほとんどの場合、同様の動作を実現できます。
  • これをプラグインとして非常に簡単に再実装します。

$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と2つのa-buttonインスタンスの両方が単一インスタンスの「直接論理子」であるためです。 、ネストを伴う複雑なビュー階層があるにもかかわらず。

私はこの時点で自分自身を繰り返していると思います。 どういうわけか、私はこの問題を回避することになります。 この議論が、なんらかの理由でもはや存在しない、かなり標準的で実用的なものへのいくつかの回避策を述べることを中心に展開されていることは、私には奇妙に思えます。

@LinusBorg :

重要なのは、チーム内の誰も、他のソリューション($ emit()だけでなく)よりも好ましい$ dispatch()の実際のユースケースを指摘できなかったということです。

これは、高速道路の出口を閉鎖しない理由を尋ねる土木技師のように私には聞こえます。

「このオフランプは、人々が左折するか右折するかについて混乱する交差点につながります。ほとんどの人はここに何年も住んでいるので道を知っていますが、新しい市民はしばしば数年間迷子になります分と私たちはそれを避けたいと思います。」

「わかりました、確かに、あなたはそれを閉じることができます、それはクールです。私は次のオフランプまでさらに10キロ移動する必要があります。私が管理します。」と私は言います。

:)お返事ありがとうございます。 少なくとも、皆さんが自由に議論できることをうれしく思います。 良いチームのようです。

これは、高速道路の出口を閉鎖しない理由を尋ねる土木技師のように私には聞こえます。

「このオフランプは、人々が左折するか右折するかについて混乱する交差点につながります。ほとんどの人はここに何年も住んでいるので道を知っていますが、新しい市民はしばしば数年間迷子になります分と私たちはそれを避けたいと思います。」

悪いメタフォアも追加します。 :)私の見解では、それはより似ています:

  • 「この道路は、人々が本来よりも速くレースをすることを奨励しています。制限速度に注意が払われることはめったにありません。人々を減速させるために、バンパーをいくつか追加する必要があります。」
  • 「でも、スピードを出して目的地に早く到着するのが好きです!」
  • 「確かに、それはあなたに数回うまくいくかもしれません、しかし私達は道路のこの部分を1。5年以上絶えず観察します、そして次のオフランプを逃した事故と人々の量は単にそれの価値がありません、多くのドライバーが持っていたようにそれらの問題の1つが証明しています。」
  • 「しかし、私はそれらのバンパーが好きではありません!」
  • さて、目的地の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時です。ありがとうございました。 後でもっと良いものを思いついた場合は投稿しますが、そうでない場合は、あなたが勝ったか、興味を失ったかのどちらかです:)

それらが再帰的ではなく、まだそのようにネストされている場合はどうなりますか?

$emit()各テンプレートに@event=リスナーを追加する必要がありますが、 $dispatch()場合はそうではありません。それだけです。

これは、冗長性と表現力のどちらを強調するかに応じて、良いか悪いかがわかります。

そしてところで。 ある状況で、親までイベントを連鎖させる必要がある場合、これは次のように実行できます。

<child-comp @event="$emit('event', $arguments)>
  • これがコンポーネント間で行う「結合」を悼みます。
  • 表現力を称賛します
  • それ以外は、入力するのは少し多いですが、大したことではありません。
  • そして、実際のユースケースの例では、グローバルストアのように、おそらく別の最適化が利用可能であると私は主張しますが、それは個々のシナリオに依存し、サンプルコードで議論するのは難しいです。

とにかく、素敵な議論、あなたの当然の睡眠を楽しんでください。

@rhyekそもそも$dispatchを使用することに決めたという理由だけで回避策のように見えますが、それは目標ではありません。 目標は、コンポーネントが適切な保守性で相互に通信できるようにすることです。 その目標を達成するとき、好みを除いてすべての実用的な長所と短所をリストすると、 $dispatchは劣った解決策であるため、私たちはそれを削除しました。

また、DOMイベントのバブリングは、コンポーネント間の通信とは根本的に異なることに注意してください。 「イベントバブリングは広く認識されている」という議論は、それが私たちが解決しようとしている問題の良い解決策でなければならないという意味ではありません。

「私はそれが好きではない」と議論するのが難しいので、私はこのスレッドでコメントを終えました。

このページは役に立ちましたか?
0 / 5 - 0 評価