Vue: haruskah vuejs2.0 menyimpan api acara $broadcast, $dispatch? Tidak ada solusi yang baik untuk mengatasi komunikasi titik ke titik orang tua-anak di 2.0

Dibuat pada 1 Sep 2016  ·  41Komentar  ·  Sumber: vuejs/vue

@yyx990803 ,
Hai, tim inti vuejs,
Saya berjuang untuk menemukan solusi yang baik untuk komunikasi titik ke titik antara komponen anak induk dengan vuejs2.0.
Karena vuejs2.0 telah menghentikan penggunaan $broadcast,$dispatch api, sangat sulit bagi saya untuk menemukan solusi alternatif yang disediakan oleh $broadcast,$dispatch dengan fitur bus acara vuejs2.0.
Saya telah menulis utas di forum tentang topik ini di sini , dan saya ingin menempelkannya di sini untuk diskusi lebih lanjut.

TOLONG JANGAN TUTUP KECUALI punya ide atau solusi bagus tentang vuejs2.0.

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

Dalam kode di atas, ketika anak dari pcom1, misalnya, soncoma $emit suatu acara, katakan,

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

di pcom, kami mendengarkan acara itu dengan

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

Saya hanya ingin pcom1 akan menangani acara itu, tetapi sayangnya pcom2 juga akan menangani itu.
Bagaimana cara mengatasi kondisi ini?

Salah satu solusi dalam aplikasi saya adalah menggunakan this.$parent sebagai bus acara
Pada anak:

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

Pada orang tua:

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

Poin negatif untuk solusi di atas adalah:

  1. kami banyak berpasangan dalam hubungan orang tua-anak;
  2. itu tidak berfungsi jika ada tingkat tingkat orang tua-anak yang lebih mendalam;

Dalam beberapa kondisi yang lebih kompleks, akan lebih sulit untuk menemukan solusi yang baik untuk sistem peristiwa khusus, misalnya, komponen rekursif

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

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

bagaimana recursivechild berkomunikasi dengan komponen pcom langsungnya?
Silakan berikan ide atau poin Anda tentang topik ini.
Terima kasih~!

discussion

Komentar yang paling membantu

@rhyek Saya ingin memberikan 2ct saya tentang beberapa poin yang Anda angkat. Karena diskusi telah membahas sejumlah topik, saya ingin kembali ke dasar tentang mengapa kita menghentikan $diospatch dan $broacast:

1. kopling implisit.

Jika Anda memiliki orang tua dan anak yang sangat bersarang yang mengirimkan suatu peristiwa, tidak ada cara untuk menyimpulkan hubungan ini dari kode (dan hal yang sama berlaku untuk $broadcast , tentu saja.)

Jika Anda melihat perubahan dan penghentian lain yang kami perkenalkan dengan Vue 2.0, Anda mungkin menyadari bahwa menghapus perilaku implisit demi alternatif eksplisit adalah tema umum, dan penghentian $dispatch cocok di sana.

Contoh:

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

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

Ini baik-baik saja ketika orang tua hanya memiliki satu anak langsung - tetapi dalam kasus itu, $emit() dengan pendengar di template juga bukan pekerjaan tambahan.

Menjadi sulit untuk diikuti (terutama dalam tim) segera setelah Anda memiliki anak-anak bersarang (terutama bersarang dalam), atau bahkan lebih dari satu anak langsung - Anda juga harus melihat semua anak, atau mengandalkan komentar kode untuk mendokumentasikan acara mana yang tiggered dari mana komponen anak - yang boilerplate tambahan, juga.

Anda mengatakan bahwa Anda menyukai $dispatch dan $broadcast karena Anda tidak harus meneruskannya melalui komponen lain. Dan saya setuju bahwa itu lebih mudah - tetapi kami belum menemukan banyak situasi di mana ini sebenarnya perlu, atau lebih tepatnya: jika ada rantai melewatkan suatu peristiwa, lebih baik datanya diubah/ ditambahkan/ selama perjalanan ini dengan komponen di antaranya.

2. Nama acara

ketika Anda menggunakan $dispatch dengan komponen yang sangat bersarang, Anda harus sangat eksplisit dalam memberi nama acara Anda, karena jika tidak, mereka bisa bentrok:

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

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

..dan jika anak-anak itu adalah lib pihak ketiga, Anda kacau sekarang. atau harus menangkap acara di beberapa komponen di tengah hanya untuk mengganti namanya sebelum Anda $dispatch() lebih jauh ke induknya. Dan jangan lupa untuk mengomentari ini, karena seseorang yang melihat kode ini mungkin berpikir mengapa Anda tidak melakukan apa-apa selain mengganti namanya.

Menggunakan $emit dan pendengar template tidak memiliki masalah ini. Anda dapat menggunakan nama acara pendek dan sederhana di mana saja, mereka tidak akan berbenturan karena setiap acara memiliki panggilan baliknya sendiri yang dilampirkan di templat @close="callback ".

Saya benar-benar hanya berharap Anda tidak mengambil *pilihan * untuk menggunakan salah satu paradigma,

Jika kami pikir kedua paradigma dapat bekerja sama dengan baik, kami akan memperlakukan mereka sama. Tapi kami tidak berpikir itu, karena alasan di atas dan banyak lagi.

Oleh karena itu, kami mencoba mengarahkan pengguna ke paket yang menurut kami paling berhasil, sambil meninggalkan cara untuk menyiasatinya dengan metode "Bus global".

Saya juga ingin berbicara tentang kekhawatiran Anda tentang keadaan global, tetapi saya tidak yakin saya memahami posisi Anda sepenuhnya.

Mungkin Anda dapat memberikan contoh di mana menurut Anda $dispatch dan $broadcast paling cocok untuk Anda, dan saya mencoba menunjukkan kepada Anda bagaimana pendekatan "kami" dapat memperbaiki situasi?

Semua 41 komentar

Karena ini adalah pembahasan proposal secara umum, saya belum membuat biola. Jika diperlukan, saya ingin membuat untuk mendemonstrasikan.
terima kasih~!

Ini telah dibenarkan pada Perubahan 2.0

Berikut salinannya:

Bagaimana Mengatasi Penghentian $dispatch dan $broadcast ?

Alasan kami menghentikan $dispatch dan $broadcast adalah karena aliran peristiwa yang bergantung pada struktur pohon komponen mungkin sulit untuk dijelaskan kapan pohon komponen menjadi besar (sederhananya: tidak skala dengan baik di aplikasi besar dan kami tidak ingin membuat Anda sakit nanti). $dispatch dan $broadcast juga tidak menyelesaikan komunikasi antar komponen saudara. Sebagai gantinya, Anda dapat menggunakan pola yang mirip dengan EventEmitter di Node.js : hub peristiwa terpusat yang memungkinkan komponen untuk berkomunikasi, di mana pun mereka berada di pohon komponen. Karena instance Vue mengimplementasikan antarmuka event emitter, Anda sebenarnya dapat menggunakan instance Vue kosong untuk tujuan itu:

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) {
 // ...
})

Pola ini dapat berfungsi sebagai pengganti $dispatch dan $broadcast dalam skenario sederhana. Tetapi untuk kasus yang lebih kompleks, disarankan untuk memperkenalkan lapisan manajemen status khusus menggunakan Vuex .

Contoh yang ditampilkan pada panduan peningkatan sama dengan yang Anda bicarakan

Tentang komunikasi rekursif: Beberapa komponen dapat mendengarkan acara yang sama. Peristiwa ini diakui oleh orang tua biasa sehingga setiap anak dapat menyadarinya

@posva , terima kasih atas informasinya. hub bus benar-benar berfungsi dengan baik dalam komunikasi titik komponen tunggal sederhana ke titik komponen tunggal. Jika ada beberapa komponen dengan jenis komponen yang sama, akan ada masalah, sayangnya, ini adalah kasus normal. Banyak kasus, yang ingin saya gunakan acara adalah memperbarui data kecil milik beberapa komponen tertentu. Implementasi bus acara saat ini tidak memberikan informasi tentang node tujuan atau asal (Saya telah melihat _uid dari setiap komponen, mungkin kita dapat menggunakan _uid unik ini untuk pengkabelan acara?), jadi vuejs2.0 sebenarnya tidak dapat mendukung komunikasi acara titik ke titik . Tepatnya, bus acara vuejs2.0 hanya mendukung komunikasi tipe komponen ke tipe komponen? Apakah ada solusi sederhana untuk mengatasi persyaratan itu: dipicu oleh peristiwa di pohon dan memperbarui DATANYA SENDIRI
vuex sangat bagus untuk manajemen data keadaan statis global tingkat aplikasi, tetapi seperti yang saya mengerti, itu mungkin tidak baik untuk manajemen data komponen lokal tertentu?
Lebih banyak pemikiran diterima tentang masalah ini.

@cnweibo Saya telah menjawab pertanyaan Anda dengan contoh di forum. Saya pikir contoh ini akan memenuhi kebutuhan Anda.
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

Apakah ada solusi sederhana untuk mengatasi persyaratan itu: dipicu oleh a
acara di pohon dan perbarui DATANYA SENDIRI

Ini diselesaikan hanya dengan vuex, tanpa sistem acara yang rumit.

vuex sangat bagus untuk manajemen data status statis global tingkat aplikasi,
tetapi seperti yang saya pahami, itu mungkin tidak baik untuk data komponen lokal tertentu
pengelolaan

'lokal' berarti komponen tunggal saja. Kasus penggunaan Anda mengelola status di seluruh
beberapa komponen, sehingga bersifat global.
Dan vuex dapat memiliki modul (subpohon status), jadi ini bukan 'variabel global'
semacam 'global'. Anda dapat menggerakkan grup komponen dengan vuex mereka sendiri
modul.

Seluruh diskusi 'peristiwa vs. status bersama' ini telah diselesaikan berbulan-bulan
lalu, dan kesimpulannya adalah menggunakan bus acara global, atau vuex. Jadi saya akan
merekomendasikan Anda untuk membaca lebih lanjut tentang vuex dan cara kerjanya.

Pada Kamis, 1 Sep 2016, 16:17 cnweibo [email protected] menulis:

@posva https://github.com/posva , terima kasih atas informasi Anda. bus
hub benar-benar berfungsi dengan baik dalam titik komponen tunggal sederhana ke komponen tunggal
komunikasi titik. Jika ada beberapa komponen dengan komponen yang sama
jenis, akan ada masalah, sayangnya, ini adalah kasus normal. Banyak
kasus, yang ingin saya gunakan acara adalah memperbarui data kecil milik beberapa
komponen tertentu. Implementasi bus acara saat ini tidak memberikan
informasi tentang node tujuan atau asal (Saya telah melihat _uid dari setiap
komponen, mungkin kita bisa menggunakan _uid unik ini untuk pengkabelan acara? ), jadi
vuejs2.0 sebenarnya tidak dapat mendukung komunikasi acara titik ke titik. Menjadi
tepat, bus acara vuejs2.0 hanya mendukung tipe komponen ke tipe komponen
komunikasi? Apakah ada solusi sederhana untuk mengatasi persyaratan itu:
dipicu oleh peristiwa di pohon dan perbarui _ITS SENDIRI DATA_
vuex sangat bagus untuk manajemen data status statis global tingkat aplikasi,
tetapi seperti yang saya pahami, itu mungkin tidak baik untuk data komponen lokal tertentu
pengelolaan?

Lebih banyak pemikiran diterima tentang masalah ini.


Anda menerima ini karena Anda berlangganan utas ini.
Balas email ini secara langsung, lihat di GitHub
https://github.com/vuejs/vue/issues/3581#issuecomment -244008699, atau bisukan
benang
https://github.com/notifications/unsubscribe-auth/AFTLl1bjHqWTVDAkr8Fqbx0WiTuH16n2ks5qlooBgaJpZM4JyUfJ
.

Saya sekarang akan menutup masalah ini, karena

  1. Solusi diberikan dan
  2. Masalah Github bukanlah tempat yang tepat untuk meminta dukungan (lihat Pedoman)

@ktsn , terima kasih atas biola demo Anda. Itulah yang saya inginkan solusi sederhana!
@fnlctrl , saya akan menghabiskan lebih banyak waktu untuk apa yang disebut manajemen negara vuex modular

terima kasih lagi~!

Menurut pendapat saya $broadcast tidak diperlukan, hanya aliran data props jatuh.
$dispatch apa pun dapat diimplementasikan kembali sebagai v-on level tunggal dan $emit seperti ini (di Vue 1):
<child-component @select="$emit('select', $arguments[0])" /> pada setiap komponen yang terlibat
Dalam situasi lain, bus acara khusus harus digunakan

Sungguh, v-on pada tag komponen untuk acara khusus pada komponen itu sendiri bekerja dengan baik dengan $emit dari komponen itu sendiri.

@cnweibo Sebagai catatan, data acara dapat diambil.

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

Tetapi data acara tidak dapat diambil di vuejs2.0

Tentu bisa, apa yang membuat Anda berpikir sebaliknya?

@fnlctrl
@LinusBorg
Maaf, saya memiliki kesalahpahaman dan membuat hal-hal tidak jelas. dalam pola yang disediakan @fnlctrl , benar-benar dapat mengambil semua data di pengendali acaranya bahkan dengan

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

Salin/tempel komentar saya sendiri dari masalah lain: https://github.com/vuejs/vue/issues/2760#issuecomment -250883407

Saya pikir menghapus $dispatch adalah ide yang buruk. Ini bukan kerangka kerja/pustaka ui pertama yang mengimplementasikan gagasan tentang tindakan/peristiwa yang menggelegak di pohon visual. Itu ide yang mapan. Mengapa menghilangkan fungsi ini dengan alasan bahwa " mampu mengirimkan peristiwa yang menyebabkan efek samping di pohon induknya yang tidak diketahui terdengar seperti resep masalah bagi saya"? Anda harus menyerahkan tanggung jawab ini kepada pengguna. Saya yakin sebagian besar memiliki akal sehat untuk menggunakan fitur ini dengan tepat. Ini bukan konsep baru!

Saya benar-benar tidak dapat melihat manfaat dari perubahan ini ketika perpustakaan ini dibangun di atas teknologi/konsep web yang sudah lama ada seperti peristiwa DOM dan DOM yang sebenarnya menggelembungkan pohon visual dan telah melakukannya selama bertahun-tahun tanpa siapa pun mengeluh. Bukankah ide komponen sesuatu yang baru-baru ini diterima berkat proposal W3C untuk komponen web? Menurut pendapat saya, Masuk akal jika komponen Vue berperilaku mirip dengan elemen DOM biasa dalam hal bagaimana penanganan acara dilakukan.

Alternatif yang diusulkan untuk menggunakan bus acara global tampaknya tidak logis bagi saya ketika sesuatu yang lebih praktis, efektif, dan lebih mudah dipahami (karena itu menjadi konsep yang mapan selama bertahun-tahun) sudah ada.

Proposal lain di utas ini mengingatkan saya tentang bagaimana EmberJS ingin melakukannya. Melewati tindakan penutupan sebagai properti ke komponen di setiap tingkat hierarki. Sangat membosankan dan tidak perlu! Vuejs adalah alasan saya menulis https://www.npmjs.com/package/ember-component-action-bubbling!

Selain itu, saya sangat menyukai perpustakaan Anda. Tapi serius, saya pikir ini adalah perubahan yang mengerikan.

Paradigma bus peristiwa hanya diusulkan sebagai solusi untuk melakukan hal yang sama persis, ketika arsitektur berbasis peristiwa sering kali lebih rendah daripada arsitektur deklaratif, berbasis negara.

Katakanlah, Anda memiliki aplikasi tempat pengguna dapat masuk. Dengan solusi berbasis peristiwa:

  1. Dengarkan acara masuk
  2. Jalankan acara nanti dengan nama pengguna dan kata sandi
  3. Tanggapi peristiwa tersebut sesuai dengan komponen apa pun yang didengarkan

Ini datang dengan beberapa masalah, meskipun. Yang terbesar adalah bahwa komponen yang tidak di-render di DOM saat acara dipecat tidak akan menerima perubahan, dan Anda tidak tahu bagian mana dari aplikasi yang akan menerima acara sama sekali. Selain itu, penerima acara tidak mungkin mengetahui dari mana acara tersebut berasal tanpa informasi tambahan yang diberikan. Maaf bahasa saya, tapi itu clusterfuck besar yang telah saya tangani dan tidak peduli untuk digunakan lagi.

Jadi mari kita gunakan pendekatan stateful:

  1. Buat variabel status global yang mewakili info akun pengguna. Ini null saat keluar, dan memiliki informasi masuk pengguna saat masuk.
  2. Saat pengguna masuk, atur info akun.

Semua yang ada di aplikasi yang bergantung pada variabel status ini diperbarui. Tidak ada kejadian, dan tidak masalah kapan atau di mana komponen dibuat, karena akan selalu menampilkan informasi yang benar. Anda bisa menggunakan acara untuk memperbarui status global, tetapi mengapa melakukannya ketika Anda bisa... memperbaruinya?

Pendekatan deklaratif memungkinkan Anda menulis komponen Anda dengan cara yang selalu muncul dengan cara yang sama tergantung persis pada keadaan lokal/global terlepas dari apa yang dilakukan pengguna dalam aplikasi Anda, tanpa harus mendengarkan sesuatu yang terjadi. Saya percaya inilah yang dimaksudkan untuk Vue selama ini, tetapi mirip dengan kebanyakan hal dalam pengembangan perangkat lunak, kami butuh beberapa saat untuk mengetahuinya. Tapi aku sangat senang kami melakukannya.

EDIT: Oh, dan jangan lupa bahwa Anda dapat melihat parameter dan, katakanlah, mengirim permintaan AJAX, atau melakukan beberapa tindakan lain ketika itu berubah. misalnya, setelah pengguna masuk, perhatikan variabel 'masuk', jika benar, muat gambar profil mereka, atau semacamnya.

Saya mengerti apa yang Anda katakan, tetapi memiliki beberapa komponen acak yang mengubah keadaan global, menurut saya, adalah hal yang sama dengan membuat komponen acak itu memunculkan suatu peristiwa yang entah di mana. Anda masih menjalankan risiko yang sama karena aliran aplikasi Anda "kotor" secara tidak sengaja.

Ada cara untuk menangani kedua paradigma dengan cara yang bersih dan biasanya (dan seharusnya) menjadi tanggung jawab pengguna kerangka kerja.

Akan ada situasi tertentu di mana satu mekanisme akan lebih masuk akal daripada yang lain. Misalnya, saya setuju bahwa status masuk harus menjadi sesuatu yang diketahui oleh seluruh aplikasi Anda: status global masuk akal. Tetapi tombol yang diklik oleh pengguna aplikasi biasanya tidak akan menangani logika di balik benar-benar login pengguna. Itu akan menjadi sesuatu yang ditangani lebih tinggi rantai. Mungkin komponen, mungkin rute. Tombol kemungkinan hanya perlu memberi tahu sesuatu tentang niat untuk masuk. Oleh karena itu, tombol tidak perlu mengubah status global Anda secara langsung.

Jadi sekarang, dengan penghapusan $dispatch, Anda memerlukan komponen tombol untuk mengetahui tentang beberapa objek global yang mengelola sesi pengguna aplikasi dan memberitahukannya secara langsung tentang maksud tersebut. Ini membuat tombol tersebut digabungkan dengan erat ke seluruh aplikasi Anda.

Atau, Anda mungkin memiliki tombol yang bersarang di 10 level dan Anda harus mendeklarasikan handler v-on:login di setiap level sehingga maksud mencapai tujuannya. Benar-benar tidak perlu.

Sebenarnya, harus melakukan v-on di setiap level hanya membuat kode Anda lebih sulit untuk dipelihara.

Jelas hanya mengubah status secara langsung bisa menjadi masalah, tetapi Vuex memecahkan masalah itu dengan mutasi dan tindakan. Dan memang benar bahwa beberapa solusi akan sesuai dengan tagihan lebih baik daripada yang lain, tetapi saya belum pernah menghadapi situasi di mana logika deklaratif bukanlah pilihan yang lebih baik.

Dalam kasus khusus Anda, saya mungkin tidak akan membuat tombol khusus untuk masuk, heh. Sebagai tambahan, jika komponen terkait login bersarang sedalam itu karena alasan tertentu, ubah saja status globalnya.

Tombol masuk hanyalah sebuah contoh. Dan toko vuex adalah apa yang saya maksud ketika saya menyebutkan "beberapa objek global". Saya harus melihat cara kerja vuex, tetapi saya berharap Anda menggabungkan beberapa komponen acak ke seluruh status aplikasi Anda hanya dengan mengelola referensi ke toko.

Ini tidak diinginkan jika, misalnya, tombol masuk adalah bagian dari beberapa perpustakaan pihak ketiga.

Saya benar-benar hanya berharap Anda tidak mengambil *_choice *_ untuk menggunakan salah satu paradigma, terutama ketika gelembung acara dikenali secara luas dan oleh karena itu mudah dipahami oleh kontributor baru pada suatu proyek.

Itu tergantung pada apa yang Anda maksud dengan "beberapa komponen acak", karena komponen tampilan router, misalnya, memiliki hak penuh untuk mengakses dan berkomitmen ke toko menurut saya. Namun, jika itu adalah komponen yang lebih kecil untuk digunakan kembali, seperti tombol, formulir, atau elemen UI lainnya, 9 kali dari 10, seharusnya tidak ada alasan logis untuk mengakses toko, lebih dari menggunakan alat peraga dan acara.

Karena data dalam aplikasi Vue bersifat top-down, Anda ingin menyimpan sebanyak mungkin status lokal Anda sebagai top-level. Deep nesting itu sendiri adalah masalah yang harus dihindari sebisa mungkin. Ini bukan _yang_ terlalu merepotkan untuk menyebarkan acara dua tingkat ke bawah, tetapi kemungkinan besar, Anda mungkin perlu memikirkan kembali struktur template Anda jika lebih dalam dari itu.

Itu sebagian besar tangen, meskipun. Sering kali, paradigma yang lebih mudah untuk dipahami adalah paradigma yang akhirnya disalahgunakan sampai ke ujung neraka dan menjadi berat. Pendekatan berbasis negara jauh lebih mudah, seperti yang disepakati oleh sebagian besar dari kita yang saat ini menggunakan 2.0. Anda bebas untuk terus menggunakan 1.0, atau beralih ke kerangka kerja lain jika pendekatan ini bukan pilihan Anda.

9 kali dari 10, seharusnya tidak ada alasan logis untuk mengakses toko, menggunakan alat peraga dan acara.

Persis poin saya.

Deep nesting itu sendiri adalah masalah yang harus dihindari sebisa mungkin

Terkadang, ini bukan pilihan.

Tidak terlalu merepotkan untuk menyebarkan acara dua tingkat ke bawah

Tidak begitu benar ketika level-level itu masuk lebih dalam.

paradigma yang lebih mudah untuk dipahami adalah paradigma yang akhirnya disalahgunakan sampai akhir neraka dan menjadi berat

Ini harus sesuai dengan disiplin pengguna Anda.

Anda bebas untuk terus menggunakan 1.0, atau beralih ke kerangka kerja lain jika pendekatan ini bukan pilihan Anda.

Mmk.

Kesederhanaan dan kenyamanan adalah alasan saya mempertimbangkan untuk beralih dari Ember ke Vue. $dispatch adalah salah satu hal yang saya nikmati tentang Vue dan menghapusnya tampaknya sangat sewenang-wenang bagi saya.

Tim menghapus banyak fitur untuk rilis 2.0. Sejujurnya saya setuju dengan mereka semua. Hanya tidak yang satu ini.

Terima kasih atas balasan Anda.

@ktsn Alternatif untuk $broadcast dan $dispatch sangat sederhana, penghapusan ini telah ditingkatkan dan menjadi lebih baik.

@rhyek Saya ingin memberikan 2ct saya tentang beberapa poin yang Anda angkat. Karena diskusi telah membahas sejumlah topik, saya ingin kembali ke dasar tentang mengapa kita menghentikan $diospatch dan $broacast:

1. kopling implisit.

Jika Anda memiliki orang tua dan anak yang sangat bersarang yang mengirimkan suatu peristiwa, tidak ada cara untuk menyimpulkan hubungan ini dari kode (dan hal yang sama berlaku untuk $broadcast , tentu saja.)

Jika Anda melihat perubahan dan penghentian lain yang kami perkenalkan dengan Vue 2.0, Anda mungkin menyadari bahwa menghapus perilaku implisit demi alternatif eksplisit adalah tema umum, dan penghentian $dispatch cocok di sana.

Contoh:

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

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

Ini baik-baik saja ketika orang tua hanya memiliki satu anak langsung - tetapi dalam kasus itu, $emit() dengan pendengar di template juga bukan pekerjaan tambahan.

Menjadi sulit untuk diikuti (terutama dalam tim) segera setelah Anda memiliki anak-anak bersarang (terutama bersarang dalam), atau bahkan lebih dari satu anak langsung - Anda juga harus melihat semua anak, atau mengandalkan komentar kode untuk mendokumentasikan acara mana yang tiggered dari mana komponen anak - yang boilerplate tambahan, juga.

Anda mengatakan bahwa Anda menyukai $dispatch dan $broadcast karena Anda tidak harus meneruskannya melalui komponen lain. Dan saya setuju bahwa itu lebih mudah - tetapi kami belum menemukan banyak situasi di mana ini sebenarnya perlu, atau lebih tepatnya: jika ada rantai melewatkan suatu peristiwa, lebih baik datanya diubah/ ditambahkan/ selama perjalanan ini dengan komponen di antaranya.

2. Nama acara

ketika Anda menggunakan $dispatch dengan komponen yang sangat bersarang, Anda harus sangat eksplisit dalam memberi nama acara Anda, karena jika tidak, mereka bisa bentrok:

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

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

..dan jika anak-anak itu adalah lib pihak ketiga, Anda kacau sekarang. atau harus menangkap acara di beberapa komponen di tengah hanya untuk mengganti namanya sebelum Anda $dispatch() lebih jauh ke induknya. Dan jangan lupa untuk mengomentari ini, karena seseorang yang melihat kode ini mungkin berpikir mengapa Anda tidak melakukan apa-apa selain mengganti namanya.

Menggunakan $emit dan pendengar template tidak memiliki masalah ini. Anda dapat menggunakan nama acara pendek dan sederhana di mana saja, mereka tidak akan berbenturan karena setiap acara memiliki panggilan baliknya sendiri yang dilampirkan di templat @close="callback ".

Saya benar-benar hanya berharap Anda tidak mengambil *pilihan * untuk menggunakan salah satu paradigma,

Jika kami pikir kedua paradigma dapat bekerja sama dengan baik, kami akan memperlakukan mereka sama. Tapi kami tidak berpikir itu, karena alasan di atas dan banyak lagi.

Oleh karena itu, kami mencoba mengarahkan pengguna ke paket yang menurut kami paling berhasil, sambil meninggalkan cara untuk menyiasatinya dengan metode "Bus global".

Saya juga ingin berbicara tentang kekhawatiran Anda tentang keadaan global, tetapi saya tidak yakin saya memahami posisi Anda sepenuhnya.

Mungkin Anda dapat memberikan contoh di mana menurut Anda $dispatch dan $broadcast paling cocok untuk Anda, dan saya mencoba menunjukkan kepada Anda bagaimana pendekatan "kami" dapat memperbaiki situasi?

Saya pikir $dispatch/$broadcast dan event bus membahas hal yang berbeda. Mereka dapat membuat kode mudah dipelihara dan dipisahkan pada skenario yang berbeda. Jika kita bisa mempertahankan keduanya, itu akan bagus.
Sangat sulit untuk mengatakan yang satu lebih baik dari yang lain dalam setiap kasus.

@cnweibo Saya pikir ada argumen yang cukup lengkap di kedua sisi, dan sejujurnya saya tidak mengerti maksud Anda tentang "mengatasi hal-hal yang berbeda". Jangan ragu untuk membuat argumen lebih lanjut, tetapi saya dapat memberi tahu Anda dengan pasti bahwa ini tidak akan terjadi.

Jika Anda benar-benar menginginkannya, tidak sulit untuk menerapkannya sendiri sebagai plugin.

@LinusBorg Saya sangat menghargai waktu yang Anda

Anda mengatakan bahwa Anda menyukai $dispatch dan $broadcast

Saya hanya suka $dispatch , jujur. $broadcast jelas tampak aneh bagi saya. Seperti yang saya katakan, $dispatch hanyalah penggelembungan acara yang ada di mana-mana di antara banyak platform saat ini. $broadcast ... tidak terlalu banyak. Satu-satunya hal serupa yang pernah saya temui adalah acara "pratinjau" di WPF yang dipasangkan dengan acara normal. Mereka "terowongan" ke bawah pohon visual dari elemen paling atas ke sumber acara asli, tetapi mereka hanya dikirim langsung ke rantai elemen terkait dan tidak _menyebar_ ke semuanya.

Anda harus sangat eksplisit dalam memberi nama acara Anda

Saya setuju dengan itu dan itu biasanya yang saya lakukan. Itu juga yang biasa dilakukan orang di jQuery. Selain itu, beberapa platform hanya mengirim objek "sumber" sebagai argumen ke pawang dan Anda mungkin dapat memfilter konteks berdasarkan itu (petunjuk: instanceof ). Acara DOM memiliki event.target tersedia, misalnya. Platform lain memiliki manfaat bekerja dengan tipe statis sehingga "bentrokan" ini cukup sulit ditemui (suatu peristiwa adalah turunan dari kelas).

Bagaimanapun, sejujurnya saya tidak mengerti mengapa ini menjadi perhatian tim VueJS. Jika orang tidak cukup berhati-hati dalam menggunakan $dispatch , saya yakin Anda dapat menemukan banyak hal lain yang mereka lakukan salah menggunakan perpustakaan Anda. Seberapa jauh Anda akan "melindungi" pengguna Anda dari kecerobohan?

Ini baik-baik saja ketika orang tua hanya memiliki satu anak langsung - tetapi dalam kasus itu, $emit() dengan pendengar di templat juga bukan pekerjaan tambahan yang nyata..

Pertanyaan jujur ​​(karena saya jelas baru mengenal Vue), selain mendeklarasikan pendengar di setiap level, bukankah Anda juga harus $emit acara pada setiap komponen di rantai? Itu sepertinya sangat mengganggu.

Sebagai kesimpulan, izinkan saya mengutip sesuatu yang dikatakan seseorang tentang masalah di vue-cli tentang memperkenalkan "template resmi" untuk proyek baru (https://github.com/vuejs/vue-cli/issues/123#issuecomment-233071630):

Seperti yang mungkin Anda ketahui, Anda tidak terkunci pada templat resmi. Ini memberi Anda kebebasan tetapi pada saat yang sama menyebabkan Anda perlu melakukan lebih banyak keputusan sendiri.

Saya pikir pada akhirnya semua hanya satu meter keseimbangan. Berapa banyak dari keputusan ini yang dapat kami buat di depan untuk semua (sebagian besar) pengguna kami dan berapa banyak atau yang mana yang ingin dilakukan sendiri oleh pengguna.

Saya setuju dengan filosofi itu, tetapi itu bukan sikap yang sama yang saya temui tentang masalah _ini_, anehnya. Kontras yang saya lihat antara komentar itu dan komentar di sini bermuara pada kebebasan. Anda mengambil pilihan berdasarkan, meskipun baik, pada akhirnya niat yang salah.

Jika Anda benar-benar menginginkannya, tidak sulit untuk menerapkannya sendiri sebagai plugin.

@yyx990803 Mungkin itulah yang _saya akan_ lakukan... mungkin.

@LinusBorg juga:

Oleh karena itu, kami mencoba mengarahkan pengguna ke paket yang menurut kami paling berhasil, sambil meninggalkan cara untuk menyiasatinya dengan metode "Bus global".

Anda tidak "mencoba mengarahkan", Anda memaksa. :)

Sudahkah Anda mencoba menerapkan fitur yang sama dengan metode dispatch dan EventBus?
Mungkin membantu

@posva Saya berencana untuk, tapi maksud saya, Anda pada dasarnya mendeklarasikan objek bus acara pada beberapa modul, dan Anda mengimpornya di mana pun Anda ingin $emit , bukan? Saya tidak suka itu, tbh. Saya pasti akan menggunakannya untuk beberapa hal, tetapi saya sangat yakin bahwa bukan itu yang ingin saya lakukan setiap saat.

Bagaimanapun, sejujurnya saya tidak mengerti mengapa ini menjadi perhatian tim VueJS. Jika orang tidak cukup berhati-hati dalam menggunakan $dispatch ,

Intinya adalah tidak ada seorang pun di tim yang dapat menunjukkan kasus penggunaan nyata untuk $dispatch() yang lebih disukai daripada solusi lain (tidak hanya $emit() , tetapi juga bus, atau global state), dan kami juga tidak melihat di banyak posting forum tentang hal itu yang kami jawab.

Ini mungkin pandangan subjektif, tetapi mungkin Anda dapat memahami bahwa jika seluruh tim berpikir "ini, menurut pengalaman kami, selalu merupakan solusi yang lebih rendah", kami membuangnya dari intinya.

Pada titik ini, saya ingin memperbarui tawaran saya untuk membahas contoh nyata.

Saya yakin Anda dapat menemukan banyak hal lain yang mereka lakukan salah menggunakan perpustakaan Anda. Seberapa jauh Anda akan "melindungi" pengguna Anda dari kecerobohan?

Ini tentu saja merupakan pertanyaan yang rumit dan keseimbangan yang sulit ditemukan. Kita harus menilai kasus demi kasus.

Ini baik-baik saja ketika orang tua hanya memiliki satu anak langsung - tetapi dalam kasus itu, $emit() dengan pendengar di templat juga bukan pekerjaan tambahan yang nyata..

Pertanyaan yang jujur ​​(karena saya jelas baru mengenal Vue), selain mendeklarasikan pendengar di setiap level, bukankah Anda juga harus $emit acara pada setiap komponen di rantai? Itu sepertinya sangat mengganggu.

Karena saya berbicara tentang hubungan langsung orang tua-anak, Anda hanya perlu $emit() sekali.

Jika Anda memiliki anak-anak yang sangat bersarang, tentu saja Anda harus memancarkan kembali di setiap level, tetapi untuk mengulanginya sendiri: Kami belum menemukan atau disajikan situasi pengiriman di banyak anak-anak bersarang benar-benar diperlukan atau lebih disukai daripada solusi lain.

Oleh karena itu, kami mencoba mengarahkan pengguna ke paket yang menurut kami paling berhasil, sambil meninggalkan cara untuk menyiasatinya dengan metode "Bus global".

Anda tidak "mencoba mengarahkan", Anda memaksa. :)

Saya akan mengatakan kami membuat hidup Anda sedikit lebih sulit - Anda bisa

  • gunakan bus, yang bukan hal yang sama tetapi dapat mencapai perilaku serupa dalam banyak kasus.
  • mengimplementasikan kembali ini sebagai plugin dengan cukup mudah.

Kami tidak memaksa Anda untuk menggunakan $emit() , kami hanya membuat jalan Anda sedikit lebih sulit.

Saya pikir Anda juga dapat menambahkannya ke setiap instance Vue: Vue.prototype.$bus = new Vue()
Tidak menyukai sesuatu sangat tidak membangun...
Saya akan menunggu contoh Anda

@posva

Saya pikir Anda juga dapat menambahkannya ke setiap instance Vue: Vue.prototype.$bus = new Vue()

Aku suka itu. Cukup pintar.

Tidak menyukai sesuatu sangat tidak konstruktif

Saya pikir itu kriteria yang cukup valid untuk memilih menggunakan sesuatu atau tidak, setidaknya untuk saya. Bagaimanapun, saya telah menyatakan berkali-kali mengapa saya pikir acara menggelegak memiliki tempatnya.

Saya akan menunggu contoh Anda

Maksudku, apakah aku benar-benar perlu? Saya telah memberikan contoh tentang situasi di mana saya tidak menyukai gagasan menggunakan bus acara atau mendeklarasikan pendengar di setiap level. Anda ingin melihat kode? Saya mungkin bisa menemukan sesuatu untuk memperjelas maksud saya, tetapi saya merasa acara menggelegak adalah hal yang cukup standar yang dapat dihargai kebanyakan orang sebagai sesuatu yang berguna, dan bus acara atau manajer negara bagian, setidaknya bagi saya, semacam Pergeseran paradigma yang, meski tidak sulit dipahami, tampak seperti wilayah hipster. 😄

Saya tentu saja bercanda tentang komentar terakhir itu. Seperti yang saya nyatakan sebelumnya, saya melihat kegunaannya dan pasti akan menemukan masalah untuk diselesaikan dengan mereka. Sebenarnya, pada beberapa proyek yang saya kerjakan menggunakan Ember, saya cenderung menulis "layanan" yang bertindak persis seperti manajer negara global. Saya yakinkan Anda, saya tidak berusaha keras kepala tentang hal ini dengan sengaja.

Saya sangat suka Vue. Saya hanya ingin _mencintainya_, Anda tahu?

bukankah kamu juga harus $emit event pada setiap komponen

Anda lakukan jika Anda berpikir dalam hal gelembung acara. Dan Anda tidak melakukannya jika Anda menggunakan komposisi komponen.

Misalnya:

<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>

Komponen a-modal tidak perlu mempedulikan kejadian komponen a-button , karena a-modal dan dua a-button instance adalah "anak logis langsung" dari satu instance , meskipun memiliki hierarki tampilan yang rumit dengan bersarang.

Saya pikir saya hanya mengulangi diri saya pada saat ini. Saya akhirnya akan mengatasi masalah ini, entah bagaimana. Tampaknya aneh bagi saya bahwa diskusi ini berkisar pada menyatakan beberapa solusi untuk sesuatu yang cukup standar dan praktis yang tidak ada lagi karena alasan apa pun.

@LinusBorg :

Intinya adalah tidak ada seorang pun di tim yang dapat menunjukkan usecase kehidupan nyata untuk $dispatch() yang lebih disukai daripada solusi lain (tidak hanya $emit()

Bagi saya ini terdengar seperti seorang insinyur sipil yang menanyakan alasan kepada saya untuk tidak menutup pintu keluar jalan raya:

Dia mengatakan sesuatu seperti, "Jalan ini mengarah ke persimpangan di mana orang menjadi bingung apakah harus belok kiri atau kanan. Kebanyakan orang tahu jalan karena mereka telah tinggal di sini selama bertahun-tahun, tetapi warga baru sering tersesat selama beberapa menit dan kami ingin menghindari itu."

Saya berkata, "Baiklah, tentu, Anda bisa menutupnya, itu keren. Saya hanya perlu melakukan perjalanan 10 km lebih jauh ke off-ramp berikutnya. Saya akan mengaturnya."

:) Terima kasih semua atas balasan Anda. Saya senang Anda semua terbuka untuk diskusi, setidaknya. Sepertinya tim yang bagus.

Bagi saya ini terdengar seperti seorang insinyur sipil yang menanyakan alasan kepada saya untuk tidak menutup pintu keluar jalan raya:

Dia mengatakan sesuatu seperti, "Jalan ini mengarah ke persimpangan di mana orang menjadi bingung apakah harus belok kiri atau kanan. Kebanyakan orang tahu jalan karena mereka telah tinggal di sini selama bertahun-tahun, tetapi warga baru sering tersesat selama beberapa menit dan kami ingin menghindari itu."

Saya akan menambahkan metafora buruk saya juga. :) Dalam pandangan saya ini lebih seperti:

  • "Jalan ini mendorong orang untuk berlomba lebih cepat dari yang seharusnya. Batas kecepatan jarang diperhatikan. Kita harus menambahkan beberapa bumper untuk memaksa orang melambat."
  • "Tapi saya suka tiba di tujuan saya dengan cepat dengan ngebut!"
  • "Tentu, itu mungkin melayani Anda dengan baik beberapa kali, tetapi kami mengamati bagian jalan ini terus-menerus selama lebih dari 1,5 tahun, dan jumlah kecelakaan dan orang-orang yang kehilangan off-ramp berikutnya sama sekali tidak sepadan, karena banyak pengemudi yang mengalami kecelakaan. salah satu masalah itu telah dibuktikan."
  • "Tapi aku tidak suka bumper itu!"
  • Nah, untuk 99% tujuan, jalan lain ini secepat yang ini sebelum bemper, ambil saja yang ini.
  • "Tapi saya tidak _suka_ jalan lain ini! Pemandangannya tidak sebagus ini!"
  • ...

Tidak menyukai sesuatu sangat tidak konstruktif

Saya pikir itu kriteria yang cukup valid untuk memilih menggunakan sesuatu atau tidak, setidaknya untuk saya. Bagaimanapun, saya telah menyatakan berkali-kali mengapa saya pikir acara menggelegak memiliki tempatnya.

Saya pikir @posva berarti: "Saya suka ini" bukan argumen konstruktif ketika mendiskusikan apakah akan menyimpan sesuatu, atau menambahkan sesuatu ke perpustakaan dengan berbagai pengguna. Itu sebabnya saya terus meminta usecase kehidupan nyata yang valid untuk didiskusikan alih-alih preferensi pribadi.

Ya, kecuali Anda meledakkan jalan raya yang sangat bagus dan membangun yang lain dengan aspal karet karena Anda membaca di suatu tempat itu cukup rapi. Juga, ini adalah tambahan 10 km. :)

Tentang contoh: Saya pikir yang diposting pada pertanyaan awal tentang komponen rekursif adalah yang ok. Bayangkan saja Anda ingin melakukan sesuatu di setiap level secara berurutan ketika sebuah peristiwa tertangkap dan Anda memiliki contoh yang sangat bagus. Melakukannya dengan $dispatch cukup mudah.

Anda ingin melihat kode?

Ya silahkan

@posva saya memberi contoh pada komentar sebelumnya. Catatan: jika Anda harus berpikir lebih dari beberapa detik bagaimana melakukannya tanpa $dispatch, itu membuktikan maksud saya.

Tentang contoh: Saya pikir yang diposting pada pertanyaan awal tentang komponen rekursif adalah yang ok. Bayangkan saja Anda ingin melakukan sesuatu di setiap level secara berurutan ketika sebuah peristiwa tertangkap dan Anda memiliki contoh yang sangat bagus. Melakukannya dengan $dispatch cukup mudah.

dengan $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>

dengan $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>

Apakah itu benar-benar lebih buruk?

Punya satu lagi? :)

Oke, tentu. Bagaimana jika mereka tidak rekursif namun masih bersarang seperti itu?

Baik. Ini jam 5 pagi dan aku akan mengalami hari yang berat berkatmu. Jika saya menemukan sesuatu yang lebih baik nanti, saya akan mempostingnya jika tidak, maka, Anda menang atau saya kehilangan minat :)

Bagaimana jika mereka tidak rekursif namun masih bersarang seperti itu?

Anda harus menambahkan pendengar @event= di setiap template untuk $emit() , dan tidak demikian untuk $dispatch() , itu saja.

Ini bisa terlihat baik atau buruk, tergantung apakah Anda menekankan verboseness vs ekspresif.

dan btw. jika dalam situasi Anda harus merantai acara hingga induknya, ini dapat dilakukan seperti:

<child-comp @event="$emit('event', $arguments)>
  • Anda akan meratapi "penggabungan" yang dilakukan antar komponen.
  • Saya akan memuji ekspresinya
  • Selain itu, sedikit lebih banyak untuk mengetik tetapi bukan masalah besar.
  • dan saya masih mengklaim, dengan contoh kasus penggunaan nyata, mungkin ada pengoptimalan berbeda yang tersedia, seperti toko global - tetapi itu tergantung pada skenario individu dan sulit untuk diperdebatkan dengan kode contoh.

Ngomong-ngomong, diskusi yang bagus, nikmati tidurmu yang memang layak.

@rhyek sepertinya solusi hanya karena Anda telah memutuskan untuk menggunakan $dispatch sejak awal, tetapi itu bukan tujuannya. Tujuannya adalah untuk memungkinkan komponen berkomunikasi satu sama lain dengan pemeliharaan yang layak. Saat mencapai tujuan itu, $dispatch adalah solusi yang lebih rendah ketika Anda mencantumkan semua pro dan kontra praktis, tidak termasuk preferensi, jadi kami membatalkannya.

Perhatikan juga gelembung acara DOM pada dasarnya berbeda dari komunikasi lintas komponen. Argumen bahwa "event bubbling diakui secara luas" tidak berarti itu harus menjadi solusi yang baik untuk masalah yang kita coba selesaikan.

Saya sudah selesai berkomentar di utas ini karena saya merasa sulit untuk berdebat dengan "Saya hanya tidak menyukainya".

Apakah halaman ini membantu?
0 / 5 - 0 peringkat