กระดูกสันหลังจะต้องพึ่งพา enderscore.js ที่จะใช้ มันจะต้องใช้ฟังก์ชั่นในขีดเส้นใต้เพื่อดำเนินการพื้นฐานการเข้าถึงองค์ประกอบหน้าและองค์ประกอบการประมวลผล
หมายเหตุ: กระดูกสันหลังทำงานได้ดีกับไลบรารี JS อื่น ๆ ดังนั้นจึงเป็นห้องสมุดไม่ใช่กรอบ
ขีดเส้นใต้ไม่ขยายวัตถุดั้งเดิม แต่เรียกใช้เมธอด _ () เพื่อห่อหุ้ม เมื่อการห่อหุ้มเสร็จสิ้นวัตถุ JS จะกลายเป็นวัตถุขีดเส้นใต้ นอกจากนี้คุณยังสามารถรับข้อมูลในวัตถุ JS ดั้งเดิมผ่านวิธีการค่า () ของวัตถุขีดล่าง (jQuery ได้รับ jQuery วัตถุผ่านวิธี $ ())
ขีดเส้นใต้มีฟังก์ชั่นทั้งหมดมากกว่า 60 ฟังก์ชั่น ตามวัตถุการประมวลผลที่แตกต่างกันสามารถแบ่งออกเป็นห้าโมดูลหลัก ได้แก่ คลาสคอลเลกชันคลาสอาร์เรย์คลาสฟังก์ชันการทำงานคลาสวัตถุและคลาสฟังก์ชั่นเครื่องมือ
Template ขีดล่าง () ฟังก์ชั่นคำอธิบาย:
ฟังก์ชั่นนี้มีสามเทมเพลต:
(1) < % %>: มีรหัสโลจิคัลและจะไม่แสดงหลังจากการเรนเดอร์
(2) < %= %>: ประเภทข้อมูลแสดงข้อมูลหลังจากการเรนเดอร์
(3) < %- %>: แปลงแท็ก HTML เป็นสตริงทั่วไปเพื่อหลีกเลี่ยงการโจมตีรหัส
รูปแบบการโทร:
_.Template (Templatestring, [data], [การตั้งค่า])
ไม่มีการใช้การเชื่อมโยงข้อมูลสองทาง
1. การห่อหุ้มวัตถุ
Underscore ไม่ได้ขยายในต้นแบบวัตถุ JavaScript ดั้งเดิม แต่ห่อหุ้มข้อมูลในวัตถุที่กำหนดเองเช่น jQuery (ต่อไปนี้เรียกว่า "Object UnderScore")
คุณสามารถรับข้อมูล JavaScript ดั้งเดิมได้โดยเรียกใช้วิธี () วิธีการของวัตถุขีดล่างตัวอย่างเช่น:
// กำหนดวัตถุ JavaScript ในตัว var jsdata = {ชื่อ: 'data'} // สร้างวัตถุเป็นวัตถุขีดล่างผ่านวิธี _ () // ต้นแบบของวัตถุ UnderScoredata มีวิธีทั้งหมดที่กำหนดไว้ใน Underscore คุณสามารถใช้ VAR UnderScoredata = _ (JSData); // รับข้อมูลเนทีฟด้วยวิธีการนั่นคือ JSDATA UnderScoredata.Value ();2. การโทรหาลำดับความสำคัญไปยัง JavaScript 1.6 วิธีการในตัว
มีวิธีการหลายวิธีในการเน้นย้ำที่รวมอยู่ในข้อกำหนดใน JavaScript 1.6 ดังนั้นภายในวัตถุขีดล่างวิธีการในตัวที่จัดทำโดยสภาพแวดล้อมโฮสต์ (หากสภาพแวดล้อมโฮสต์ได้ใช้วิธีการเหล่านี้) จะถูกเรียกก่อนเพื่อปรับปรุงประสิทธิภาพการดำเนินการของฟังก์ชัน
สำหรับสภาพแวดล้อมของโฮสต์ที่ไม่รองรับ JavaScript 1.6, UnderScore จะนำไปใช้ในแบบของตัวเองและสำหรับนักพัฒนาเหล่านี้มีความโปร่งใสอย่างสมบูรณ์
สภาพแวดล้อมโฮสต์ที่กล่าวถึงในที่นี้อาจเป็นสภาพแวดล้อมที่ใช้งาน Node.js หรือเบราว์เซอร์ไคลเอนต์
3. เปลี่ยนเนมสเปซ
Underscore ใช้ _ (ขีดเส้นใต้) โดยค่าเริ่มต้นในการเข้าถึงและสร้างวัตถุ แต่ชื่อนี้อาจไม่สอดคล้องกับข้อกำหนดการตั้งชื่อของเราหรืออาจทำให้เกิดความขัดแย้งในการตั้งชื่อได้อย่างง่ายดาย
เราสามารถเปลี่ยนชื่อของขีดเส้นใต้ผ่านวิธี noconflict () และคืนค่าค่าก่อนตัวแปร _ (ขีดล่าง) ตัวอย่างเช่น:
<script type = "text/javascript"> var _ = 'ตัวแปรที่กำหนดเอง'; </script> <script type = "text/javascript" src = "underscore/underscore-min.js"> </script> <script type = "text/javascript"> // underscore object console.dir (_); // เปลี่ยนชื่อวัตถุขีดเส้นใต้ให้เราแล้วเข้าถึงและสร้างวัตถุขีดล่างผ่านเรา var us = _.noconflict (); // เอาต์พุต "ตัวแปรที่กำหนดเอง" คอนโซล DIR (_); </script>
4. การทำงานของลูกโซ่
จำได้ไหมว่าเราดำเนินการลิงก์ใน jQuery ได้อย่างไร? ตัวอย่างเช่น:
$ ('a') .css ('ตำแหน่ง', 'ญาติ') .attr ('href', '#') .show ();ขีดเส้นใต้ยังสนับสนุนการดำเนินงานของห่วงโซ่ แต่คุณต้องเรียกวิธีการที่โซ่ () เพื่อประกาศ:
var arr = [10, 20, 30]; _ (arr). chain () .map (ฟังก์ชั่น (รายการ) {return item ++;}). first () .value ();หากมีการเรียกวิธี Chain () UnderScore จะห่อหุ้มวิธีที่เรียกว่าในการปิดให้ห่อหุ้มค่าการส่งคืนลงในวัตถุขีดล่างและส่งคืน:
// นี่เป็นฟังก์ชั่นหลักในการเน้นย้ำถึงการใช้งานโซ่ มันห่อหุ้มค่าการส่งคืนลงในวัตถุขีดล่างใหม่และเรียกใช้เมธอดโซ่ () อีกครั้งเพื่อให้การสนับสนุนสำหรับฟังก์ชั่นถัดไปในห่วงโซ่วิธีการ var result = function (obj, chain) {return chain? _ (obj). chain (): obj; -5. ขยายขีดความสามารถ
เราสามารถขยายวิธีการที่กำหนดเองเป็นแบบขีดเส้นใต้ผ่านวิธี MixIn () ได้อย่างง่ายดายเช่น:
_.mixin ({method1: ฟังก์ชั่น (วัตถุ) {// toDo}, method2: ฟังก์ชัน (arr) {// toDo}, method3: function (fn) {// toDo}});วิธีการเหล่านี้จะถูกผนวกเข้ากับวัตถุต้นแบบขีด จำกัด ซึ่งสามารถใช้งานได้โดยวัตถุที่สร้างขีดความสามารถทั้งหมดและพวกเขาสนุกกับสภาพแวดล้อมเช่นเดียวกับวิธีอื่น ๆ
6. สำรวจคอลเลกชัน
วิธีการแต่ละ () และแผนที่ () เป็นวิธีที่ใช้กันมากที่สุดสองวิธี พวกเขาจะใช้ซ้ำผ่านคอลเลกชัน (อาร์เรย์หรือวัตถุ) และประมวลผลแต่ละองค์ประกอบในการรวบรวมเช่น:
var arr = [1, 2, 3]; _ (arr) .map (ฟังก์ชั่น (รายการ, i) {arr [i] = item + 1;}); var obj = {ครั้งแรก: 1, วินาที: 2} _ (obj) .Each (ฟังก์ชัน (ค่า, คีย์) {return obj [key] = value + 1;});เมธอด MAP () มีบทบาทและพารามิเตอร์เดียวกันกับแต่ละเมธอด () แต่จะบันทึกผลลัพธ์ที่ส่งคืนโดยแต่ละฟังก์ชันการวนซ้ำไปยังอาร์เรย์ใหม่และส่งคืน
7. ฟังก์ชั่นการควบคุมปริมาณ
ฟังก์ชั่นการควบคุมปริมาณหมายถึงการควบคุมความถี่การดำเนินการหรือช่วงเวลาของฟังก์ชัน (เช่นประตูที่ควบคุมการไหลของน้ำ) Underscore มีสองวิธี: debounce () และ throttle () สำหรับฟังก์ชั่นการควบคุมปริมาณ
เพื่ออธิบายวิธีการทั้งสองนี้ให้ชัดเจนยิ่งขึ้นสมมติว่าเราจำเป็นต้องใช้สองข้อกำหนด:
ข้อกำหนดที่ 1: เมื่อผู้ใช้เข้าสู่เกณฑ์การค้นหาในกล่องข้อความคำหลักที่ตรงกันจะถูกสอบถามโดยอัตโนมัติและแจ้งให้ผู้ใช้ (เช่นเดียวกับเมื่อป้อนคำค้นหาการค้นหาใน TMALL)
ก่อนอื่นวิเคราะห์ข้อกำหนดแรก เราสามารถผูกเหตุการณ์คีย์กดของกล่องข้อความ เมื่อเนื้อหาของกล่องอินพุตเปลี่ยนไปสอบถามคำหลักที่ตรงกันและแสดง สมมติว่าฉันต้องการสอบถาม "Windows Phone" ซึ่งมี 13 อักขระและใช้เวลาเพียง 1 วินาทีเท่านั้นที่ฉันจะทำอินพุตให้เสร็จสมบูรณ์ (ดูเหมือนจะเร็วไปหน่อยนั่นคือความหมาย) จากนั้นภายใน 1 วินาทีนี้วิธีการสืบค้นเรียกว่า 13 ครั้ง นี่เป็นสิ่งที่น่ากลัวมากและถ้า Tmall ถูกนำไปใช้เช่นนี้ฉันกังวลว่ามันจะตายก่อนวันเดี่ยว (แน่นอนมันไม่ได้บอบบาง แต่มันไม่ใช่ทางออกที่ดีที่สุด)
วิธีที่ดีกว่าคือการสืบค้นคำหลักที่ตรงกันเมื่อผู้ใช้ได้ป้อนข้อมูลเสร็จหรือกำลังรอพรอมต์ (บางทีเขาอาจขี้เกียจเกินไปที่จะป้อนเนื้อหาต่อไปนี้)
ในที่สุดเราก็พบว่าในทั้งสองกรณีที่เราคาดหวังผู้ใช้จะหยุดการป้อนข้อมูลชั่วคราวดังนั้นเราจึงตัดสินใจสอบถามหลังจากผู้ใช้หยุดการป้อนข้อมูลเป็นเวลา 200 มิลลิวินาที (หากผู้ใช้พิมพ์เนื้อหาอยู่ตลอดเวลาเราคิดว่าเขาอาจชัดเจนเกี่ยวกับคำหลักที่เขาต้องการ
ในเวลานี้การใช้ฟังก์ชั่น Debounce () ในขีดล่างเราสามารถใช้ข้อกำหนดนี้ได้อย่างง่ายดาย:
<อินพุต type = "text" id = "search" name = "search" /> <script type = "text /javascript"> var query = _ (function () {// การดำเนินการค้นหาที่นี่}). debounce (200); $ ('#search'). bind ('keypress', แบบสอบถาม); </script>คุณจะเห็นว่ารหัสของเรารัดกุมมากและการควบคุมการควบคุมปริมาณได้ถูกนำไปใช้ในวิธีการ debounce () เราบอกเพียงว่าหากฟังก์ชั่นการสืบค้นไม่ได้ถูกเรียกภายใน 200 มิลลิวินาทีเราจะดำเนินการค้นหาแบบสอบถามของเราจากนั้นผูกฟังก์ชันการสืบค้นกับเหตุการณ์คีย์นิพจน์ในกล่องอินพุต
ฟังก์ชั่นการสืบค้นเกิดขึ้นได้อย่างไร? เมื่อเราเรียกวิธี Debounce () เราจะผ่านฟังก์ชั่นที่ดำเนินการค้นหาและเวลา (มิลลิวินาที) วิธีการ debounce () จะควบคุมการทำงานตามเวลาที่เราผ่านและส่งคืนฟังก์ชั่นใหม่ (เช่นฟังก์ชันการสืบค้น) เราสามารถเรียกฟังก์ชั่นการสืบค้นด้วยความมั่นใจและความกล้าหาญและวิธี Debounce () จะช่วยให้เราควบคุมได้ตามต้องการ
ข้อกำหนดที่ 2: เมื่อผู้ใช้ลากแถบเลื่อนเบราว์เซอร์ให้โทรติดต่ออินเทอร์เฟซเซิร์ฟเวอร์เพื่อตรวจสอบว่ามีเนื้อหาใหม่
มาวิเคราะห์ข้อกำหนดที่สองกันเถอะ เราสามารถผูกวิธีการสืบค้นกับเหตุการณ์ที่เกิดขึ้นได้ แต่นี่ไม่ใช่วิธีปฏิบัติที่ดีเพราะผู้ใช้ลากแถบเลื่อนหนึ่งครั้งและอาจทำให้เกิดเหตุการณ์ onscroll หลายสิบหรือหลายร้อยเหตุการณ์
เราสามารถใช้วิธีการ Debounce () ด้านบนเพื่อทำการควบคุมการควบคุมปริมาณได้หรือไม่? เมื่อผู้ใช้ลากแถบเลื่อนเสร็จแล้วสอบถามสำหรับเนื้อหาใหม่? แต่สิ่งนี้ไม่สอดคล้องกับข้อกำหนดและผู้ใช้หวังว่าจะเห็นการเปลี่ยนแปลงในเนื้อหาใหม่ในระหว่างกระบวนการลาก
ดังนั้นเราจึงตัดสินใจที่จะทำสิ่งนี้: เมื่อผู้ใช้ลากช่วงเวลาระหว่างการสืบค้นทุกสองครั้งจะไม่น้อยกว่า 500 มิลลิวินาทีหากผู้ใช้ลากเป็นเวลา 1 วินาทีสิ่งนี้อาจทำให้เกิดเหตุการณ์ onscroll 200 ครั้ง แต่เราทำแบบสอบถาม 2 ข้อเท่านั้น
การใช้วิธีการเค้น () ในขีดเส้นใต้เรายังสามารถใช้ข้อกำหนดนี้ได้อย่างง่ายดาย:
<script type = "text/javascript"> var query = _ (ฟังก์ชั่น () {// การดำเนินการค้นหาที่นี่}). เค้น (500); $ (หน้าต่าง). -bind ('Scroll', Query); </script>รหัสยังคงรัดกุมมากเพราะภายในวิธีการเค้น () การควบคุมทั้งหมดที่เราใช้มีอยู่แล้ว
คุณอาจพบว่าทั้งสองวิธีของการ debounce () และ chottle () มีความคล้ายคลึงกันมาก (รวมถึงวิธีการโทรและค่าส่งคืน) แต่ฟังก์ชั่นของพวกเขาแตกต่างกัน
พวกเขาทั้งหมดใช้สำหรับการควบคุมปริมาณฟังก์ชั่นและฟังก์ชั่นการควบคุมไม่ได้เรียกว่าบ่อยครั้งบันทึกทรัพยากรไคลเอนต์และเซิร์ฟเวอร์
วิธี Debounce () มุ่งเน้นไปที่ช่วงเวลาระหว่างการดำเนินการฟังก์ชั่นนั่นคือเวลาการโทรของฟังก์ชั่นสองครั้งไม่น้อยกว่าเวลาที่กำหนด
เมธอดเค้น () มุ่งเน้นไปที่ความถี่ในการดำเนินการของฟังก์ชันมากขึ้นนั่นคือฟังก์ชั่นจะถูกเรียกเพียงครั้งเดียวภายในความถี่ที่ระบุ
8. การวิเคราะห์เทมเพลต
Underscore ให้ฟังก์ชั่นการแยกวิเคราะห์เทมเพลตที่มีน้ำหนักเบาซึ่งช่วยให้เราจัดระเบียบโครงสร้างหน้าและตรรกะได้อย่างมีประสิทธิภาพ
ฉันจะแนะนำด้วยตัวอย่าง:
<!-ใช้เพื่อแสดงแท็กที่แสดงผล-> <ul id = "องค์ประกอบ"> </ul> <!-กำหนดเทมเพลตและใส่เนื้อหาเทมเพลตลงในแท็กสคริปต์-> <สคริปต์ประเภท = "ข้อความ/เทมเพลต" id = "tpl"> <%สำหรับ (var i = 0; <%= item.lastName%> </span> <pan> <%-item.city%> </pan> </li> <%}%> </script> <script type = "text/javascript" src = "underscore/underscore-min.js"> </script> < tpl = $ ('#tpl'). html (); // สร้างข้อมูลซึ่งอาจเป็นข้อมูล var ที่คุณได้รับจากเซิร์ฟเวอร์ = {list: [{firstName: '<a href = "#"> จาง </a>', นามสกุล: 'San', เมือง: 'Shanghai'}, {FirstName: 'Li' 'Wang', LastName: 'Wu', City: 'Guangzhou'}, {FirstName: 'Zhao', นามสกุล: 'Liu', City: 'Shenzhen'}]} // การแยกเทมเพลตกลับเนื้อหาที่แยกวิเคราะห์ html = _.template // เติมเนื้อหาที่แยกวิเคราะห์ไปยังองค์ประกอบการเรนเดอร์องค์ประกอบ html (html); </script>ในตัวอย่างนี้เราใส่เนื้อหาเทมเพลตลงในแท็ก <script> คุณอาจสังเกตเห็นว่าประเภทของแท็กคือข้อความ/เทมเพลตแทนข้อความ/JavaScript เนื่องจากไม่สามารถเรียกใช้โดยตรงเป็นสคริปต์ JavaScript
ฉันขอแนะนำให้คุณใส่เนื้อหาเทมเพลตใน <Script> เพราะถ้าคุณเขียนลงใน <div> หรือแท็กอื่น ๆ พวกเขาอาจถูกเพิ่มเข้าไปในแผนผัง DOM เพื่อแยกวิเคราะห์ (แม้ว่าคุณจะซ่อนแท็กนี้มันจะไม่หลีกเลี่ยง)
_.Template เทมเพลตฟังก์ชั่นสามารถแยกวิเคราะห์แท็กเทมเพลตได้เพียง 3 ประเภทเท่านั้น (ซึ่งง่ายกว่า Smarty และ JSTL มาก):
< % %>: ใช้ในการมีรหัส JavaScript ที่จะดำเนินการเมื่อข้อมูลถูกแสดงผล
< %= %>: ใช้ในการส่งออกข้อมูลอาจเป็นตัวแปรแอตทริบิวต์ของวัตถุหรือการเรียกใช้ฟังก์ชัน (เพื่อส่งออกค่าส่งคืนของฟังก์ชัน)
< %- %>: ใช้ในการส่งออกข้อมูลและแปลงอักขระ HTML ที่มีอยู่ในข้อมูลเป็นรูปแบบเอนทิตี (ตัวอย่างเช่นจะแปลงคำพูดสองครั้งเป็นแบบฟอร์ม) เพื่อหลีกเลี่ยงการโจมตี XSS
เมื่อเราต้องการแสดง HTML ในข้อมูลเป็นข้อความเรามักจะใช้แท็ก < %- %>
ขีดเส้นใต้ยังช่วยให้คุณสามารถปรับเปลี่ยนแท็ก 3 รูปแบบเหล่านี้ได้ หากเราต้องการใช้ { % %}, { %= %}, { %- %} เป็นแท็กเราสามารถทำได้โดยการปรับเปลี่ยน templatesettings เช่นนี้:
_.templatesettings = {การประเมินผล: // {%([/s/s]+?)/%/}/g, interpolate: // {%= ([/s/s]+?)/%/}/g, หลบหนี: // {%-([/s/s]ในตัวอย่างนี้เราผ่านเนื้อหาเทมเพลตและข้อมูลที่จะเติมไปยังวิธีเทมเพลตซึ่งจะถูกประมวลผลในลำดับต่อไปนี้:
(1) แยกวิเคราะห์เนื้อหาเทมเพลตลงใน JavaScript ที่เรียกใช้งานได้ (แท็กแม่แบบแยกวิเคราะห์)
(2) แก้ไขขอบเขต JavaScript ที่แยกวิเคราะห์ไปยังวัตถุข้อมูลที่เราผ่านด้วยคำสั่งซึ่งช่วยให้เราสามารถเข้าถึงคุณสมบัติของวัตถุข้อมูลโดยตรงผ่านตัวแปรในเทมเพลต
(3) เรียกใช้ JavaScript ที่แยกวิเคราะห์ (การกรอกข้อมูลลงในเทมเพลต)
(4) ส่งคืนผลลัพธ์หลังจากดำเนินการ
เรามักจะพบสถานการณ์ที่วิธีการเทมเพลตเรียกว่าหลายครั้งเพื่อแสดงผลข้อมูลไปยังเทมเพลตเดียวกัน
สมมติว่าเรามีรายการเพจและข้อมูลแต่ละชิ้นในรายการจะแสดงผลผ่านเทมเพลต เมื่อผู้ใช้เข้าสู่หน้าถัดไปเราจะได้รับข้อมูลของหน้าถัดไปและแสดงผลอีกครั้ง ในความเป็นจริงเทมเพลตจะเหมือนกันทุกครั้งที่มีการแสดงผล แต่กระบวนการประมวลผลทั้งหมดของเทมเพลตที่อธิบายไว้ตอนนี้จะถูกดำเนินการเสมอ
ในความเป็นจริงวิธีเทมเพลตของขีดล่างให้วิธีการโทรที่มีประสิทธิภาพมากขึ้น เราแก้ไขสองประโยคสุดท้ายในรหัสด้านบนเป็น:
// แยกวิเคราะห์เทมเพลต, ส่งคืนเนื้อหาที่แยกวิเคราะห์ var render = _.template (tpl); var html = render (ข้อมูล); // เติมเนื้อหาที่แยกวิเคราะห์ไปยังองค์ประกอบการเรนเดอร์. html (html);
คุณจะพบความแตกต่างเล็กน้อย: เมื่อเราเรียกวิธีการเทมเพลตเราจะผ่านเนื้อหาเทมเพลตเท่านั้น แต่ไม่ใช่ข้อมูล ในเวลานี้วิธีการเทมเพลตจะแยกวิเคราะห์เนื้อหาเทมเพลตสร้างรหัส JavaScript ที่ใช้งานได้แยกวิเคราะห์และส่งคืนฟังก์ชั่นและฟังก์ชั่นร่างกายเป็น JavaScript ที่แยกวิเคราะห์ ดังนั้นเมื่อเราเรียกฟังก์ชั่นนี้เพื่อแสดงผลข้อมูลเราจะละเว้นการวิเคราะห์การแยกวิเคราะห์แม่แบบ
คุณควรจัดเก็บฟังก์ชั่นที่ส่งคืน (เช่นเดียวกับที่ฉันเก็บไว้ในตัวแปรเรนเดอร์) จากนั้นแสดงข้อมูลโดยเรียกใช้ฟังก์ชันโดยเฉพาะอย่างยิ่งหากเทมเพลตเดียวกันอาจแสดงผลหลายครั้ง การทำเช่นนั้นสามารถปรับปรุงประสิทธิภาพการดำเนินการ (การปรับปรุงเฉพาะควรขึ้นอยู่กับความยาวและความซับซ้อนของแม่แบบของคุณ แต่มันก็เป็นนิสัยที่ดีอยู่ดี)