Saya memiliki tiga cara berbeda untuk menginisialisasi dan membuat tampilan dan subview, dan masing-masing memiliki masalah yang berbeda. Saya ingin tahu apakah ada cara yang lebih baik yang menyelesaikan semua masalah:
Skenario Satu:
Inisialisasi anak-anak dalam fungsi inisialisasi orang tua. Dengan cara ini, tidak semua macet di render sehingga ada lebih sedikit pemblokiran pada rendering.
initialize : function () {
//parent init stuff
this.child = new Child();
},
render : function () {
this.$el.html(this.template());
this.child.render().appendTo(this.$('.container-placeholder');
}
Masalah:
Masalah terbesar adalah bahwa memanggil render pada orang tua untuk kedua kalinya akan menghapus semua binding acara anak-anak. (Ini karena cara kerja jQuery
$.html()
.) Ini dapat dikurangi dengan meneleponthis.child.delegateEvents().render().appendTo(this.$el);
saja, tetapi kemudian yang pertama, dan yang paling sering, Anda melakukan lebih banyak pekerjaan yang tidak perlu.Dengan menambahkan anak-anak, Anda memaksa fungsi render untuk memiliki pengetahuan tentang struktur DOM orang tua sehingga Anda mendapatkan pemesanan yang Anda inginkan. Yang berarti mengubah templat mungkin memerlukan memperbarui fungsi render tampilan.
Skenario Dua:
Inisialisasi anak-anak di initialize()
masih orang tua , tetapi alih-alih menambahkan, gunakan setElement().delegateEvents()
untuk mengatur anak ke elemen dalam template orang tua.
initialize : function () {
//parent init stuff
this.child = new Child();
},
render : function () {
this.$el.html(this.template());
this.child.setElement(this.$('.placeholder-element')).delegateEvents().render();
}
Masalah:
- Ini membuat yang
delegateEvents()
diperlukan sekarang, yang sedikit negatif di atasnya hanya diperlukan pada panggilan berikutnya dalam skenario pertama.
Skenario Tiga:
Inisialisasi anak-anak dalam metode orangtua render()
sebagai gantinya.
initialize : function () {
//parent init stuff
},
render : function () {
this.$el.html(this.template());
this.child = new Child();
this.child.appendTo($.('.container-placeholder').render();
}
Masalah:
Ini berarti bahwa fungsi render sekarang harus diikat dengan semua logika inisialisasi juga.
Jika saya mengedit status salah satu tampilan anak, dan kemudian memanggil render pada orang tua, anak yang sama sekali baru akan dibuat dan semua status saat ini akan hilang. Yang juga sepertinya bisa jadi tidak pasti karena kebocoran memori.
Sangat penasaran untuk membuat orang lain menerima ini. Skenario apa yang akan Anda gunakan? atau adakah magis keempat yang memecahkan semua masalah ini?
Apakah Anda pernah melacak status yang diberikan untuk Tampilan? Ucapkan renderedBefore
bendera? Tampak sangat janky.
sumber
delegateEvents()
setelahsetElement()
? Sesuai dokumen: "... dan pindahkan acara yang didelegasikan tampilan dari elemen lama ke yang baru",setElement
metode itu sendiri harus menangani delegasi acara kembali.Jawaban:
Ini pertanyaan yang bagus. Backbone bagus karena kurangnya asumsi yang dibuatnya, tetapi itu berarti Anda harus (memutuskan bagaimana) mengimplementasikan hal-hal seperti ini sendiri. Setelah melihat-lihat barang saya sendiri, saya menemukan bahwa saya (jenis) menggunakan campuran skenario 1 dan skenario 2. Saya tidak berpikir skenario ajaib ke-4 ada karena, cukup sederhana, semua yang Anda lakukan dalam skenario 1 & 2 harus selesai
Saya pikir akan lebih mudah untuk menjelaskan bagaimana saya ingin menanganinya dengan sebuah contoh. Katakanlah saya memiliki halaman sederhana ini dipecah menjadi tampilan yang ditentukan:
Katakan HTML, setelah dirender, kira-kira seperti ini:
Semoga cukup jelas bagaimana HTML cocok dengan diagram.
The
ParentView
memegang 2 pandangan anak,InfoView
danPhoneListView
juga beberapa div tambahan, salah satunya#name
, perlu diatur di beberapa titik.PhoneListView
memiliki pandangan anak sendiri, sebuah arrayPhoneView
entri.Demikian pertanyaan Anda yang sebenarnya. Saya menangani inisialisasi dan rendering berbeda berdasarkan tipe tampilan. Saya memecah pandangan saya menjadi dua jenis,
Parent
pandangan danChild
pandangan.Perbedaan di antara mereka sederhana,
Parent
pandangan menahan pandangan anak sementaraChild
pandangan tidak. Jadi, dalam contoh saya,ParentView
danPhoneListView
yangParent
dilihat, sementaraInfoView
danPhoneView
entriChild
pandangan.Seperti yang saya sebutkan sebelumnya, perbedaan terbesar antara kedua kategori ini adalah ketika mereka diizinkan untuk membuat. Di dunia yang sempurna, saya ingin
Parent
pandangan hanya ditampilkan sekali. Terserah pandangan anak mereka untuk menangani rendering ulang ketika model berubah.Child
di sisi lain, saya mengizinkan untuk merender ulang kapan pun mereka butuhkan karena mereka tidak memiliki pandangan lain yang mengandalkannya.Secara lebih rinci, untuk
Parent
tampilan saya sukainitialize
fungsi saya untuk melakukan beberapa hal:InfoView
akan ditugaskan#info
).Langkah 1 cukup jelas.
Langkah 2, rendering, dilakukan agar setiap elemen yang dilihat anak mengandalkan sudah ada sebelum saya mencoba untuk menetapkannya. Dengan melakukan ini, saya tahu semua anak
events
akan diatur dengan benar, dan saya dapat merender ulang blok mereka sebanyak yang saya inginkan tanpa khawatir harus mendelegasikan ulang apa pun. Saya tidak benarrender
- benar melihat anak di sini, saya membiarkan mereka melakukan itu di dalam mereka sendiriinitialization
.Langkah 3 dan 4 sebenarnya ditangani pada saat yang sama ketika saya masuk
el
sambil membuat tampilan anak. Saya suka melewatkan elemen di sini karena saya merasa orang tua harus menentukan di mana dalam pandangannya sendiri anak diizinkan untuk meletakkan kontennya.Untuk rendering, saya mencoba membuatnya tetap sederhana untuk
Parent
dilihat. Saya inginrender
fungsi tidak lebih dari membuat tampilan induk. Tidak ada delegasi acara, tidak ada rendering tampilan anak, tidak ada. Hanya membuat sederhana.Kadang-kadang ini tidak selalu berhasil. Misalnya dalam contoh saya di atas,
#name
elemen harus diperbarui setiap kali nama dalam model berubah. Namun, blok ini adalah bagian dariParentView
template dan tidak ditangani oleh tampilan khususChild
, jadi saya mengatasinya. Saya akan membuat semacamsubRender
fungsi yang hanya menggantikan konten#name
elemen, dan tidak harus membuang seluruh#parent
elemen. Ini mungkin tampak seperti peretasan, tapi saya benar-benar menemukan itu bekerja lebih baik daripada harus khawatir tentang rendering ulang seluruh DOM dan elemen-elemen pemasangan kembali dan semacamnya. Jika saya benar-benar ingin membuatnya bersih, saya akan membuat tampilan baruChild
(mirip denganInfoView
) yang akan menangani#name
blok.Sekarang untuk
Child
tampilan,initialization
sangat mirip denganParent
tampilan, hanya tanpa penciptaanChild
tampilan lebih lanjut . Begitu:Child
rendering tampilan juga sangat sederhana, cukup render dan atur konten sayael
. Sekali lagi, jangan main-main dengan delegasi atau semacamnya.Berikut ini beberapa contoh kode
ParentView
tampilan saya :Anda dapat melihat implementasi saya di
subRender
sini. Dengan memiliki perubahan yang terikatsubRender
alih-alihrender
, saya tidak perlu khawatir tentang peledakan dan membangun kembali seluruh blok.Berikut contoh kode untuk
InfoView
blok:Ikatan adalah bagian penting di sini. Dengan mengikat ke model saya, saya tidak perlu khawatir menyebut
render
diri saya secara manual . Jika model berubah, blok ini akan merender ulang sendiri tanpa memengaruhi tampilan lainnya.The
PhoneListView
akan mirip denganParentView
, Anda hanya perlu logika sedikit lebih baik Andainitialization
danrender
fungsi untuk menangani koleksi. Cara Anda menangani koleksi benar-benar terserah Anda, tetapi Anda setidaknya harus mendengarkan acara pengumpulan dan memutuskan bagaimana Anda ingin me-render (menambahkan / menghapus, atau hanya me-render ulang seluruh blok). Saya pribadi ingin menambahkan tampilan baru dan menghapus yang lama, bukan membuat ulang seluruh tampilan.The
PhoneView
akan hampir identik denganInfoView
, hanya mendengarkan perubahan model itu peduli.Semoga ini sedikit membantu, tolong beri tahu saya jika ada sesuatu yang membingungkan atau tidak cukup detail.
sumber
render
ke dalaminitialize
metode ini adalah praktik yang buruk, karena itu mencegah Anda menjadi lebih berkinerja dalam kasus-kasus di mana Anda tidak ingin langsung membuat. Apa yang Anda pikirkan tentang ini?PhoneListView
?Saya tidak yakin apakah ini langsung menjawab pertanyaan Anda, tetapi saya pikir itu relevan:
http://lostechies.com/derickbailey/2011/10/11/backbone-js-getting-the-model-for-a-clicked-element/
Konteks di mana saya membuat artikel ini berbeda, tentu saja, tetapi saya pikir dua solusi yang saya tawarkan, bersama dengan pro dan kontra dari masing-masing, harus membuat Anda bergerak ke arah yang benar.
sumber
Bagi saya sepertinya bukan ide terburuk di dunia untuk membedakan antara pengaturan intital dan pengaturan tampilan Anda selanjutnya melalui semacam flag. Untuk membuat ini bersih dan mudah bendera harus ditambahkan ke tampilan Anda sendiri yang harus memperpanjang tampilan Backbone (Base).
Sama seperti Derick Saya tidak sepenuhnya yakin apakah ini langsung menjawab pertanyaan Anda, tetapi saya pikir mungkin paling tidak layak disebutkan dalam konteks ini.
sumber
Kevin Peel memberikan jawaban yang bagus - ini versi tl; dr saya:
sumber
Saya mencoba untuk tidak menggabungkan antara tampilan seperti ini. Ada dua cara yang biasa saya lakukan:
Gunakan router
Pada dasarnya, Anda membiarkan fungsi router Anda menginisialisasi tampilan orang tua dan anak. Jadi pandangan tidak memiliki pengetahuan satu sama lain, tetapi router menangani semuanya.
Melewati el yang sama ke kedua tampilan
Keduanya memiliki pengetahuan tentang DOM yang sama, dan Anda dapat memesannya sesuai keinginan Anda.
sumber
Apa yang saya lakukan adalah memberikan identitas kepada masing-masing anak (yang telah dilakukan Backbone untuk Anda: cid)
Ketika Container melakukan rendering, menggunakan 'cid' dan 'tagName' menghasilkan placeholder untuk setiap anak, jadi dalam templat anak-anak tidak tahu tentang di mana ia akan diletakkan oleh Container.
daripada yang bisa Anda gunakan
tidak diperlukan placeholder yang ditentukan, dan Container hanya menghasilkan placeholder daripada struktur DOM anak-anak. Cotainer dan Anak-anak masih menghasilkan elemen DOM sendiri dan hanya sekali.
sumber
Berikut ini adalah mixin ringan untuk membuat dan merender subview, yang menurut saya mengatasi semua masalah di utas ini:
https://github.com/rotundasoftware/backbone.subviews
Pendekatan yang dilakukan oleh plug ini adalah membuat dan membuat subview setelah pertama kali tampilan induk diberikan. Kemudian, pada render tampilan induk yang berikutnya, $ .detach elemen subview, render kembali parent, lalu masukkan elemen subview di tempat yang sesuai dan render ulang. Dengan cara ini, subview objek digunakan kembali pada render berikutnya, dan tidak perlu mendelegasikan kembali peristiwa.
Perhatikan bahwa kasus tampilan koleksi (di mana masing-masing model dalam koleksi diwakili dengan satu subview) sangat berbeda dan pantas dibahas / solusi sendiri saya pikir. Solusi umum terbaik yang saya ketahui tentang hal ini adalah CollectionView di Marionette .
EDIT: Untuk kasing tampilan koleksi, Anda mungkin juga ingin melihat implementasi yang lebih berfokus pada UI ini , jika Anda memerlukan pilihan model berdasarkan klik dan / atau menyeret dan menjatuhkan untuk menyusun ulang.
sumber