นี่เป็นคำถามที่ยอดเยี่ยม Backbone นั้นยอดเยี่ยมเพราะไม่มีข้อสันนิษฐาน แต่มันก็หมายความว่าคุณต้อง (ตัดสินใจว่าจะทำอย่างไร) ให้ทำสิ่งต่าง ๆ เช่นนี้ด้วยตัวคุณเอง หลังจากตรวจสอบสิ่งต่าง ๆ ของตัวเองฉันพบว่าฉัน (ชนิด) ใช้การผสมผสานของสถานการณ์สมมติ 1 และสถานการณ์ 2 ฉันไม่คิดว่ามีสถานการณ์เวทย์มนตร์ที่ 4 อยู่เพราะเพียงพอทุกสิ่งที่คุณทำในสถานการณ์ 1 และ 2 จะต้องเป็น เสร็จแล้ว
ฉันคิดว่ามันจะง่ายที่สุดในการอธิบายวิธีที่ฉันชอบจัดการกับตัวอย่าง ว่าฉันมีหน้าง่าย ๆ นี้แบ่งออกเป็นมุมมองที่ระบุ:

สมมติว่า HTML คือหลังจากที่ถูกเรนเดอร์แล้วสิ่งนี้:
<div id="parent">
<div id="name">Person: Kevin Peel</div>
<div id="info">
First name: <span class="first_name">Kevin</span><br />
Last name: <span class="last_name">Peel</span><br />
</div>
<div>Phone Numbers:</div>
<div id="phone_numbers">
<div>#1: 123-456-7890</div>
<div>#2: 456-789-0123</div>
</div>
</div>
หวังว่ามันชัดเจนว่า HTML นั้นสอดคล้องกับไดอะแกรมอย่างไร
ParentViewถือ 2 views เด็กInfoViewและPhoneListViewเช่นเดียวกับไม่กี่ divs พิเศษหนึ่งซึ่ง#nameจะต้องมีการตั้งค่าในบางจุด PhoneListViewเก็บมุมมองลูกของตัวเองอาร์เรย์ของPhoneViewรายการ
ดังนั้นคำถามที่แท้จริงของคุณ ฉันจัดการกับการเริ่มต้นและการแสดงผลแตกต่างกันไปตามประเภทการดู ฉันแบ่งมุมมองของฉันออกเป็นสองประเภทParentมุมมองและChildมุมมอง
ความแตกต่างระหว่างสิ่งเหล่านี้เป็นเรื่องง่ายParentมุมมองจะเก็บมุมมองของเด็กไว้ในขณะที่Childมุมมองไม่ได้ ดังนั้นในตัวอย่างของฉันParentViewและPhoneListViewมีParentมุมมองในขณะที่InfoViewและPhoneViewรายการที่มีChildมุมมอง
อย่างที่ฉันพูดไว้ก่อนหน้านี้ความแตกต่างที่ยิ่งใหญ่ที่สุดระหว่างสองหมวดหมู่คือเมื่อพวกเขาได้รับอนุญาตให้แสดงผล ในโลกที่สมบูรณ์แบบฉันต้องการParentมุมมองที่จะแสดงเพียงครั้งเดียว มันขึ้นอยู่กับมุมมองลูกของพวกเขาที่จะจัดการกับการเรนเดอร์ใด ๆ เมื่อมีการเปลี่ยนแปลงรูปแบบ Childในทางกลับกันฉันอนุญาตให้แสดงผลอีกครั้งเมื่อใดก็ได้ที่ต้องการเนื่องจากไม่มีมุมมองอื่นที่ต้องพึ่งพา
ในรายละเอียดเพิ่มเติมเล็กน้อยสำหรับParentมุมมองที่ฉันชอบinitializeฟังก์ชั่นของฉันที่จะทำบางสิ่ง:
- เริ่มต้นมุมมองของฉันเอง
- ทำให้มุมมองของฉันเอง
- สร้างและเริ่มต้นมุมมองลูก ๆ
- กำหนดให้เด็กแต่ละคนดูองค์ประกอบภายในมุมมองของฉัน (เช่น
InfoViewจะได้รับมอบหมาย#info)
ขั้นตอนที่ 1 เป็นคำอธิบายที่ค่อนข้างดี
ขั้นตอนที่ 2 การเรนเดอร์เสร็จสิ้นเพื่อให้องค์ประกอบใด ๆ ที่มุมมองลูกพึ่งพานั้นมีอยู่ก่อนที่ฉันจะพยายามกำหนดมัน ด้วยการทำเช่นนี้ฉันรู้ว่าเด็กทุกคนeventsจะได้รับการตั้งค่าอย่างถูกต้องและฉันสามารถแสดงบล็อกของพวกเขาซ้ำได้หลายครั้งตามที่ฉันต้องการโดยไม่ต้องกังวลว่าจะต้องมอบหมายอะไรอีก ฉันไม่จริงrenderเด็ก ๆ initializationมุมมองที่นี่ผมช่วยให้พวกเขาที่จะทำภายในของตัวเอง
ขั้นตอนที่ 3 และ 4 ได้รับการจัดการในเวลาเดียวกับที่ฉันผ่านเข้าไปelในขณะที่สร้างมุมมองเด็ก ฉันชอบที่จะส่งองค์ประกอบในที่นี่เพราะฉันรู้สึกว่าผู้ปกครองควรพิจารณาว่าเด็ก ๆ ได้รับอนุญาตให้ใส่เนื้อหาในมุมมองของตัวเองได้อย่างไร
สำหรับการเรนเดอร์ฉันพยายามทำให้มันค่อนข้างง่ายสำหรับParentมุมมอง ฉันต้องการให้renderฟังก์ชั่นไม่ทำอะไรมากไปกว่าการสร้างมุมมองพาเรนต์ ไม่มีการมอบหมายกิจกรรมไม่มีการแสดงผลมุมมองลูกไม่มีอะไร เพียงแค่เรนเดอร์ที่เรียบง่าย
บางครั้งมันก็ไม่ได้ผลเสมอไป เช่นในตัวอย่างด้านบน#nameองค์ประกอบจะต้องได้รับการอัปเดตทุกครั้งที่ชื่อในโมเดลเปลี่ยนแปลง อย่างไรก็ตามบล็อกนี้เป็นส่วนหนึ่งของParentViewเทมเพลตและไม่ได้รับการจัดการโดยChildมุมมองเฉพาะดังนั้นฉันจึงแก้ไขมัน ฉันจะสร้างsubRenderฟังก์ชั่นบางอย่างที่แทนที่เฉพาะเนื้อหาของ#nameองค์ประกอบและไม่ต้องทิ้ง#parentองค์ประกอบทั้งหมด นี่อาจดูเหมือนแฮ็ค แต่ฉันพบว่ามันใช้งานได้ดีกว่าไม่ต้องกังวลเกี่ยวกับการเรนเดอร์ DOM ทั้งหมดและติดตั้งองค์ประกอบและสิ่งเหล่านี้อีกครั้ง ถ้าฉันต้องการทำให้มันสะอาดจริงๆฉันจะสร้างChildมุมมองใหม่(คล้ายกับInfoView) ที่จะจัดการกับ#nameบล็อก
ตอนนี้สำหรับChildมุมมองแล้วinitializationจะคล้ายกับParentมุมมองโดยไม่สร้างChildมุมมองเพิ่มเติมใด ๆ ดังนั้น:
- เริ่มต้นมุมมองของฉัน
- การตั้งค่าผูกมัดการฟังการเปลี่ยนแปลงใด ๆ กับรูปแบบที่ฉันสนใจ
- ทำให้มุมมองของฉัน
Childelมุมมองการแสดงผลยังเป็นง่ายมากเพียงแค่การแสดงผลและการตั้งค่าเนื้อหาของฉัน อีกครั้งไม่ยุ่งกับการมอบหมายหรืออะไรอย่างนั้น
นี่คือตัวอย่างรหัสของสิ่งที่ฉันParentViewอาจมีลักษณะ:
var ParentView = Backbone.View.extend({
el: "#parent",
initialize: function() {
// Step 1, (init) I want to know anytime the name changes
this.model.bind("change:first_name", this.subRender, this);
this.model.bind("change:last_name", this.subRender, this);
// Step 2, render my own view
this.render();
// Step 3/4, create the children and assign elements
this.infoView = new InfoView({el: "#info", model: this.model});
this.phoneListView = new PhoneListView({el: "#phone_numbers", model: this.model});
},
render: function() {
// Render my template
this.$el.html(this.template());
// Render the name
this.subRender();
},
subRender: function() {
// Set our name block and only our name block
$("#name").html("Person: " + this.model.first_name + " " + this.model.last_name);
}
});
คุณสามารถดูการใช้งานของฉันsubRenderที่นี่ ด้วยการเปลี่ยนแปลงที่ถูกผูกไว้กับsubRenderแทนที่จะrenderทำให้ฉันไม่ต้องกังวลเกี่ยวกับการระเบิดและสร้างใหม่ทั้งบล็อก
นี่คือตัวอย่างโค้ดสำหรับInfoViewบล็อก:
var InfoView = Backbone.View.extend({
initialize: function() {
// I want to re-render on changes
this.model.bind("change", this.render, this);
// Render
this.render();
},
render: function() {
// Just render my template
this.$el.html(this.template());
}
});
การผูกเป็นส่วนสำคัญที่นี่ การผูกเข้ากับโมเดลของฉันทำให้ฉันไม่ต้องกังวลกับการโทรหาrenderตัวเอง หากรูปแบบการเปลี่ยนแปลงบล็อกนี้จะแสดงตัวเองอีกครั้งโดยไม่มีผลต่อมุมมองอื่น ๆ
สิ่งPhoneListViewนี้จะคล้ายกับParentViewคุณเพียงแค่ต้องใช้ตรรกะเพิ่มขึ้นเล็กน้อยทั้งในinitializationและrenderฟังก์ชั่นของคุณเพื่อจัดการคอลเลกชัน วิธีที่คุณจัดการกับคอลเลกชันนั้นขึ้นอยู่กับคุณ แต่อย่างน้อยคุณจะต้องฟังเหตุการณ์ของคอลเลกชันและตัดสินใจว่าคุณต้องการเรนเดอร์อย่างไร (ผนวก / ลบหรือเพียงแสดงบล็อกทั้งหมดอีกครั้ง) ฉันเป็นการส่วนตัวที่จะผนวกมุมมองใหม่และลบมุมมองเก่าออกไปไม่แสดงมุมมองทั้งหมดอีกครั้ง
PhoneViewจะเกือบจะเหมือนกันกับInfoViewเพียงการฟังการเปลี่ยนแปลงรูปแบบที่ใส่ใจเกี่ยวกับ
หวังว่านี่จะช่วยได้เล็กน้อยโปรดแจ้งให้เราทราบหากมีสิ่งที่ทำให้เกิดความสับสนหรือมีรายละเอียดไม่เพียงพอ