Angular เป็นสิ่งที่ดีในกรอบ MVVM แต่ด้วยกรอบขนาดใหญ่และครอบคลุมเช่นนี้จึงไม่ต่ำที่จะเรียนรู้และต้องใช้เวลาอย่างน้อยหนึ่งหรือสองสัปดาห์ในการเริ่มต้น Knockoutjs มุ่งเน้นไปที่การผูกข้อมูลและสามารถใช้งานได้ในเวลาเพียงหนึ่งหรือสองวันดังนั้นค่าใช้จ่ายในการเรียนรู้ไม่ควรต่ำเกินไป! ในยุคที่วิวัฒนาการส่วนหน้าเร็วมากค่าใช้จ่ายในการเรียนรู้ก็เป็นปัจจัยที่ต้องพิจารณา หลายครั้งที่โครงการของเราไม่ซับซ้อนและพวกเขาไม่ต้องการกรอบสากล พวกเขาต้องการเครื่องมือที่ง่ายและง่าย
ก่อนที่ knockoutjs
สมมติว่าเรากำลังสร้างระบบการสั่งซื้อและจำเป็นต้องแสดงราคาต่อหน่วยของผลิตภัณฑ์จากนั้นเราสามารถคำนวณราคารวมตามปริมาณอินพุตและแสดง นอกจากนี้ยังง่ายที่จะบรรลุด้วยรหัสดั้งเดิมเอฟเฟกต์คือ:
รหัสมีดังนี้:
<!-รหัส HTML-> ราคา: <span id = "ราคา"> </span> <br /> บัญชี: <อินพุต type = "text" id = "บัญชี" value = "" placeholder = "โปรดป้อนปริมาณ" /> <br /> sum: <span id = "sum"> </span> document.getElementById ('บัญชี'), sumnode = document.getElementById ('ผลรวม'), ราคา = 100, บัญชี = 11, ผลรวม = ราคา * บัญชี; // เริ่มต้น pricenode.innerText = ราคา; accountNode.Value = บัญชี; sumnode.textContent = sum; // ตรวจสอบอินพุตผู้ใช้ของ Layer Layer AccountNode.addeVentListener ('Keydown', ฟังก์ชั่น (e) {window.settimeout (ฟังก์ชัน ()มันค่อนข้างง่าย! โอ้โดยวิธีการที่เราแสดงรายการละ 50 รายการและมีจอแสดงผล 10 ประเภทรวมถึงโปรโมชั่นต่างๆเช่นการซื้อ Okamoto 5 กล่องและได้รับแป้งทอด ...
ดังนั้นคุณรู้ปัญหาของการใช้งานดั้งเดิม:
•ด้วยการเพิ่มขึ้นของ UI และการโต้ตอบข้อมูลจำนวนรหัสเพิ่มขึ้นอย่างรวดเร็วและยากที่จะรักษา
•ชื่อที่อิงตามคำค้นหา DOM, ID หรือคลาสนั้นยากที่จะจัดการ
•การเชื่อมต่อรหัสสูงยากที่จะนำกลับมาใช้ใหม่
รู้เบื้องต้นเกี่ยวกับ Knockoutjs
Knockoutjs (ต่อไปนี้จะเรียกว่า KO) ปรากฏขึ้นเพื่อแก้ปัญหาข้างต้น มันเป็นไลบรารี MVVM ที่มีน้ำหนักเบาที่มุ่งเน้นไปที่การใช้การเชื่อมโยงข้อมูลและมุมมอง มันไม่ได้ให้คลาส UI และฟังก์ชั่นการกำหนดเส้นทางและมันเร็วมากที่จะเริ่มต้น ในเวลาเดียวกันเนื่องจาก KO ออกมาหลายปีแล้วมันจึงกลายเป็นกรอบที่ค่อนข้างเป็นผู้ใหญ่ เมื่อทำบางหน้าที่แสดงแบบไดนามิกมากขึ้น KO เป็นตัวเลือกที่ดีกว่าอย่างไม่ต้องสงสัย ฉันจะไม่พูดมากเกี่ยวกับ MVVM เพียงแค่ภาพที่จะทำให้สับสน:
KO ขึ้นอยู่กับคุณสมบัติหลักสามประการ (บทนำสู่เว็บไซต์ทางการ):
1. การติดตามที่สังเกตได้และการพึ่งพา: ใช้สิ่งที่สังเกตได้เพื่อตั้งค่าห่วงโซ่ความสัมพันธ์โดยนัยระหว่างข้อมูลโมเดลสำหรับการแปลงข้อมูลและการเชื่อมโยง
2. การเชื่อมโยงที่ประกาศ: ใช้ไวยากรณ์ที่ง่ายและง่ายต่อการอ่านเพื่อผูกข้อมูลโมเดลกับองค์ประกอบ DOM ได้อย่างง่ายดาย
3. Templating: เอ็นจิ้นเทมเพลตในตัวเขียนงานนำเสนอ UI ที่ซับซ้อนอย่างรวดเร็วสำหรับข้อมูลโมเดลของคุณ
การใช้ KO นั้นง่ายมาก เพียงดาวน์โหลดโดยตรงไปยังเว็บไซต์ทางการ (http://knockoutjs.com/index.html) และแนะนำด้วย <script>
วัตถุที่สังเกตได้
เขียนตัวอย่างข้างต้นอีกครั้งโดยใช้ KO (ราคาที่กำหนดเองซึ่งเป็นหนึ่งในความปรารถนาในวัยเด็กของฉัน):
รหัสมีลักษณะเช่นนี้:
<!-รหัส html-> <div id = "หนึ่ง"> ราคา: <อินพุตประเภท = "ข้อความ" data-bind = "value: price" placeholder = "โปรดป้อนราคาหน่วย" /> <br /> บัญชี: <อินพุตประเภท = "ข้อความ" data-bind = "value: placeolder = ฟังก์ชั่น (p, a) {// ตั้งค่าเป็นวัตถุที่สังเกตได้และเริ่มต้นสิ่งนี้ price = ko.observable (p); this.account = ko.observable (a); // เมื่อเรียกฟังก์ชัน KO สิ่งนี้จะถูกส่งผ่านเป็นอย่างอื่น this.sum = ko.pureComputed (function () {// เนื่องจากวัตถุที่สังเกตได้คือวัตถุฟังก์ชันคุณต้องใช้ราคา () เพื่ออ่านค่าปัจจุบัน // ตั้งค่าโดยใช้ราคา (newValue) และรองรับการเขียนโซ่ 10); // ใช้การผูกมัดนี้และการผูกมัดเริ่มมีผล ko.applybindings (VM);1) มาดูรหัส HTML ก่อน:
คุณจะเห็นว่าคู่คีย์-ค่าเช่น data-bind = "xx: oo" ถูกเพิ่มเข้าไปในแต่ละแท็ก นี่คือไวยากรณ์ที่มีผลผูกพันของ KO XXOO เป็นตัวแทนอะไร? (xxoo? ผู้เขียนยังคงเป็นเด็ก ... ) จากตัวอย่างเราจะเห็นได้ว่าแอตทริบิวต์ของ xx เป็นแท็กซึ่งสามารถเป็นแอตทริบิวต์แท็กเช่นข้อความค่าคลาสคลาสตรวจสอบ ฯลฯ และในความเป็นจริงพวกเขายังสามารถคลิกโฟกัสโหลดและเหตุการณ์ DOM อื่น ๆ OO ดูเหมือนตัวแปร แต่ไม่ใช่ตัวแปร แต่เป็นวัตถุฟังก์ชัน การดำเนินการฟังก์ชั่นนี้ (ด้วย A ()) สามารถรับค่าขอบเขตที่สอดคล้องกันได้ ผ่าน XXOO คุณลักษณะหรือเหตุการณ์ขององค์ประกอบสามารถผูกมัดกับวัตถุฟังก์ชันใน JS (ถ้า XXOO คุณต้องรับผิดชอบซึ่งกันและกัน) นี่คือการผูกมัดการประกาศของ KO คำจำกัดความของการผูกเป็นโหมดผู้สังเกตการณ์ แต่นี่คือการผูกสองทาง ผู้เผยแพร่และผู้สมัครสมาชิกสมัครรับข้อความของกันและกัน นี่คือการผูกสองทางของ MVVM ผลลัพธ์ของการผูกมัดแบบสองทิศทาง KO คือฝ่ายหนึ่งสามารถอัปเดตบุคคลอื่นโดยอัตโนมัติโดยการเปลี่ยนแปลงนั่นคือข้อมูลและชั้นนำเสนอจะถูกผูกไว้อย่างแน่นหนาผ่าน ViewModel เอฟเฟกต์การผูกจะคล้ายกับ:
2) มาดูรหัส JS:
คุณจะเห็นได้ว่าวัตถุ ViewModel ถูกกำหนดไว้ใน JS และ OO ที่ถูกผูกไว้ใน HTML นั้นทำงานในวัตถุ มีการดำเนินการหลักสองประการที่นี่: KO.observable () และ Ko.pureComputed ()
• KO.observable (P): ดูชื่อนี่คือวิธีการตั้งค่าวัตถุที่สังเกตได้ พารามิเตอร์ที่ผ่าน P คือค่าเริ่มต้น พารามิเตอร์ที่นี่อาจเป็นประเภทข้อมูลพื้นฐานหรือวัตถุ JSON หลังจากตั้งค่าเป็นที่สังเกตได้หมายความว่าระบบจะสังเกตค่านี้ตลอดเวลา ไม่ว่าจะเป็น P ใน ViewModel หรือ P ในการเปลี่ยนแปลงวัตถุที่ถูกผูกไว้จะทำให้เกิดเหตุการณ์รีเฟรชและสถานที่ทั้งหมดที่ใช้ค่านี้จะได้รับการปรับปรุงเป็นสถานะล่าสุด เห็นได้ชัดว่าวัตถุที่สังเกตได้นั้นค่อนข้างใช้เวลานานดังนั้นสำหรับค่าที่ไม่ต้องการการเปลี่ยนแปลงแบบไดนามิก (เช่นราคา) ไม่ได้ตั้งเป็นวัตถุที่สังเกตได้ แน่นอนว่ามันยังคงต้องใส่เข้าไปใน ViewModel เพื่อเริ่มต้นจากส่วนกลาง
•หมายเหตุ: วัตถุที่สังเกตได้ที่ส่งคืนโดย KO.observable (P) เป็นวัตถุฟังก์ชันดังนั้นคุณต้องใช้ราคา () เพื่ออ่านวัตถุที่สังเกตได้; ในทำนองเดียวกันการตั้งค่าวัตถุที่สังเกตได้ต้องใช้ราคา (newValue) เพื่อใช้ราคา (newValue) สิ่งที่มีน้ำใจมากขึ้นคือเมื่อการตั้งค่ามันรองรับการเขียนโซ่: ViewModel.price (100) .Account (10)
• ko.pureComputed () เป็นสิ่งที่เรียกว่าการติดตามการพึ่งพา นี่คือราคาต่อหน่วย * ปริมาณเท่ากับราคารวม โปรดทราบว่าคุณไม่สามารถใช้ this.sum = this.price () * this.account () โดยตรง; เพื่อระบุผลรวม วิธีการเขียนนี้ไม่สามารถรีเฟรชวัตถุที่ถูกผูกไว้แบบไดนามิก แต่เปลี่ยนตัวแปรผลรวมแบบไดนามิก แต่จำเป็นต้องมีการดำเนินการอื่น ๆ เพื่อรีเฟรชวัตถุที่ถูกผูกไว้ ดังนั้นค่าที่มีผลผูกพันที่เกี่ยวข้องกับการคำนวณจะต้องตั้งค่าโดยใช้ฟังก์ชันการคำนวณของ KO แน่นอนวัตถุฟังก์ชั่นที่ส่งคืนเป็นวัตถุฟังก์ชัน นอกจากนี้ KO ยังมีฟังก์ชั่นที่คำนวณได้ซึ่งสามารถตั้งค่าได้ แต่ขอแนะนำให้ใช้ Pure เพื่อปรับปรุงประสิทธิภาพ
•ให้ความสนใจกับวิธีการเขียนที่นี่: ko.pureComputed (fn, this), นั่นคือผูก fn กับขอบเขต ViewModel ซึ่งจริงๆแล้วคือการโทร/ใช้ใน JS เนื่องจากนี่เป็นวัตถุ KO เมื่อดำเนินการฟังก์ชั่นภายใน KO เพื่อให้ได้ขอบเขตของวัตถุ ViewModel จึงต้องส่งผ่านไปยังวิธีการเขียนด้านบน แน่นอนคุณสามารถใช้สิ่งนั้นเพื่อบันทึกวัตถุ ViewModel นอกฟังก์ชั่น KO จากนั้นใช้สิ่งนั้นภายในฟังก์ชั่น KO เพื่อเรียกวัตถุ ViewModel แบบนี้:
var that = this; this.sum = ko.purecomputed (ฟังก์ชัน () {return that.price () * that.account ();});หลังจากกำหนดคอนสตรัคเตอร์ ViewModel วัตถุ ViewModel จะถูกสร้างอินสแตนซ์และจากนั้นใช้วิธี KO.ApplyBindings () เพื่อให้มีผลผูกพัน อย่าพลาดขั้นตอนนี้
โหมดหน้าง่ายโดยใช้ KO:
<!-รหัส html-> <span data-bind = "text: bindtext"> </span> // js codevar viewModel = {bindText: ko.observable ('initValue')}; ko.applyBindings (viewModel);โดยสรุปแล้วคือ: ใช้ data-bind = "xx: oo" เพื่อประกาศการเชื่อมโยงใน HTML สร้าง viewModel ใน JS และตั้งค่าวัตถุที่สังเกตได้และใช้การเชื่อมโยงในที่สุด
อาร์เรย์วัตถุที่สังเกตได้
มาดูการใช้อาร์เรย์วัตถุที่สังเกตได้ ใน KO อาร์เรย์และตัวแปรไม่สามารถผสมได้เช่น JS สำหรับวัตถุอาร์เรย์คุณต้องใช้ ko.observablearray ([…, …]) ในลักษณะเดียวกัน ในทำนองเดียวกันองค์ประกอบอาร์เรย์อาจเป็นประเภทพื้นฐานหรือวัตถุ JSON อาร์เรย์วัตถุที่สังเกตได้ใน KO มีชุดของวิธีการทำงานของอาร์เรย์เช่น slice (), sort (), push () ฯลฯ เอฟเฟกต์เหมือนกับวิธีการทำงานของอาร์เรย์ JS ดั้งเดิม ความแตกต่างเพียงอย่างเดียวระหว่างการเปลี่ยนแปลงที่ทำผ่านวิธี KO จะได้รับแจ้งให้ผู้สมัครใช้งานรีเฟรชอินเทอร์เฟซ แต่วิธี JS จะไม่รีเฟรชอินเทอร์เฟซ นี่คือตัวอย่างง่ายๆ:
<!-รหัส html-> <เลือก data-bind = "ตัวเลือก: list"> </select> // js codevar vm = {// list: ko.observablearray () รายการ: ko.observablearray (['luffy', 'zoro', 'sanji'])};จุดสำคัญ: KO ตรวจสอบสถานะของอาร์เรย์ไม่ใช่สถานะขององค์ประกอบเอง กล่าวคือเมื่อสถานะการเปลี่ยนแปลงของอาร์เรย์ (เพิ่มองค์ประกอบ) เหตุการณ์ KO จะถูกกระตุ้นให้ทำให้วัตถุที่ถูกผูกไว้จะรีเฟรช แต่การเปลี่ยนแปลงในองค์ประกอบภายในอาร์เรย์ (เช่นการเปลี่ยนแปลงค่า) จะไม่ถูกตรวจสอบและไม่สามารถเรียกเหตุการณ์ KO ได้ ตัวอย่างเช่น:
การใช้วิธีการดั้งเดิมเพื่อเปลี่ยน Luffy เป็น Lucy ในคอนโซลแบบไดนามิกจะไม่รีเฟรชหน้า UI ในขณะที่ใช้อาร์เรย์ของ KO เพื่อเปลี่ยนอาร์เรย์จะรีเฟรชหน้าทันที เป็นที่น่าสังเกตว่าเมื่อรีเฟรชการเปลี่ยนแปลงก่อนหน้านี้จะได้รับการรีเฟรช (Luffy> Lucy) กล่าวอีกนัยหนึ่งตัวแปรในหน่วยความจำ JS มีการเปลี่ยนแปลงจริง แต่ก็ยังขาดการกระทำเพื่อรีเฟรช DOM อย่างที่คุณเห็นที่นี่วิธีการอ่านอาร์เรย์คือ vm.list () [0] เนื่องจากรายการเป็นวัตถุฟังก์ชันและการดำเนินการค่าส่งคืนเป็นเนื้อหารายการที่เราต้องการ ในทำนองเดียวกันคุณสามารถรีเซ็ตอาร์เรย์วัตถุที่สังเกตได้ผ่าน vm.list (["girl", "girl"]) และรีเฟรช UI ทันที
หากคุณต้องการตอบสนองการเปลี่ยนแปลงขององค์ประกอบอาร์เรย์ไปยัง UI แบบไดนามิกคุณจะต้องตั้งค่าองค์ประกอบอาร์เรย์เป็นวัตถุที่สังเกตได้จากนั้นใช้วิธีการของ KO เพื่อเปลี่ยนค่าองค์ประกอบอาร์เรย์ โปรดทราบว่าการใช้รายการวิธีการของ KO () [0] ("Lucy")!
มีวิธีการสองประเภทสำหรับการใช้งานอาร์เรย์วัตถุที่สังเกตได้ หนึ่งคือชื่อเดียวกับวิธีการอาร์เรย์ JS ดั้งเดิม: ป๊อป, ผลัก, กะ, unshift, reverse, เรียงลำดับ, splice ส่วนนี้เหมือนกับการใช้งานและผลกระทบของวิธี JS ดั้งเดิมดังนั้นฉันจะไม่ทำซ้ำอีกครั้ง
วิธีอื่น ๆ บางอย่างไม่สามารถใช้ได้ใน JS ส่วนใหญ่ดังนี้:
•ลบ (SomeItem) - ลบรายการองค์ประกอบทั้งหมดที่มีค่าเท่ากันไปยัง SomeItem และส่งคืนในรูปแบบอาร์เรย์ สิ่งนี้หมายความว่าที่นี่คือคุณไม่สามารถลบรายการรายการแรกได้โดยตรง remove (0) แต่ใช้รายการแบบฟอร์ม remove (list () [0]) เพื่อลบออก ในระยะสั้นพารามิเตอร์ที่ผ่านจะต้องเป็นค่าของรายการองค์ประกอบ มันสามารถใช้ในรูปแบบของรายการ () [0] หรือคุณสามารถป้อนสตริงค่าโดยตรง (เช่น "luffy")
•ลบ (ฟังก์ชั่น (รายการ) {return item.age <18;}) - ลบรายการองค์ประกอบทั้งหมดด้วยแอตทริบิวต์อายุน้อยกว่า 18 และส่งคืนเป็นอาร์เรย์ การใช้งานนี้ไม่แตกต่างจากฟังก์ชั่นลำดับที่สูงกว่าอาร์เรย์ทั่วไป รายการจะถูกส่งผ่านเป็นพารามิเตอร์ของฟังก์ชั่นลำดับที่สูงกว่า เมื่อวนซ้ำผ่านอาร์เรย์รายการจะถูกลบเมื่อค่าส่งคืนของฟังก์ชั่นการสั่งซื้อที่สูงขึ้นคือค่าที่แท้จริงมิฉะนั้นจะไปที่รายการถัดไป
• RemoveAll (['Chad', 132, undefined]) - ลบรายการองค์ประกอบทั้งหมดที่มีค่าเท่ากับ 'Chad' หรือ 123 หรือไม่ได้กำหนดและส่งคืนเป็นอาร์เรย์
• RemoveAll () - ลบรายการทั้งหมดและส่งคืนเป็นอาร์เรย์
เคล็ดลับ: เมื่อจัดการกับวัตถุที่สังเกตได้หากมีวัตถุและการโต้ตอบบ่อยครั้งการรีเฟรชทันทีกับการเปลี่ยนแปลงแต่ละครั้งจะใช้ประสิทธิภาพ ในเวลานี้คุณสามารถใช้ส่วนขยาย myobservablearray.extend ({ratelimit: 1,000}) เพื่อตั้งค่าการรีเฟรชล่าช้า ตัวอย่างเช่นเมื่อแทรกองค์ประกอบอย่างต่อเนื่องลงในอาร์เรย์ที่สังเกตได้คุณสามารถตั้งเวลารอบ 1,000ms เพื่อรวมการดำเนินการทั้งหมดภายใน 1,000ms ให้เป็นรีเฟรชเพื่อหลีกเลี่ยงการเสื่อมสภาพของประสิทธิภาพที่เกิดจากการทำงานของ DOM บ่อยครั้ง
สรุป
บทความนี้ส่วนใหญ่แนะนำแนวคิดที่สำคัญที่สุดใน KnockoutJs: วัตถุที่สังเกตได้ (อาร์เรย์) วัตถุที่สังเกตได้คือวัตถุฟังก์ชันเป็นหลัก เมื่อใช้งานวัตถุที่สังเกตได้ผ่านวิธี KO UI สามารถรีเฟรชแบบไดนามิกได้ นี่คือวิธีที่แนะนำ ในเวลาเดียวกันคุณสามารถใช้งานวัตถุที่สังเกตได้ด้วยวิธี JS ดั้งเดิม แต่วิธีการดั้งเดิมจะไม่รีเฟรชการแสดง UI และคุณจะต้องรอจนกว่าเหตุการณ์รีเฟรชครั้งต่อไปจะรีเฟรชไปยัง UI