KnockoutJS เป็นกรอบ MVVM ที่ใช้งาน JavaScript ดีมาก. ตัวอย่างเช่นหลังจากเพิ่มหรือลดรายการข้อมูลรายการไม่จำเป็นต้องรีเฟรชส่วนควบคุมทั้งหมดหรือเขียน JS Addition และการลบโหนดด้วยตัวเอง เพียงกำหนดเทมเพลตและแอตทริบิวต์ที่ตรงตามคำจำกัดความของไวยากรณ์ พูดง่ายๆคือเราต้องให้ความสนใจกับการเข้าถึงข้อมูลเท่านั้น
1. บทนำ
เนื่องจากระบบของ บริษัท จำเป็นต้องได้รับการปรับปรุงใหม่เมื่อเร็ว ๆ นี้ฉันวางแผนที่จะใช้ KnockoutJS เพื่อสร้างเว็บ front-end สำหรับระบบใหม่ที่ปรับปรุงใหม่ ในระหว่างกระบวนการฉันพบปัญหา - วิธีใช้ knockoutjs เพื่อทำฟังก์ชั่นการปนเปื้อนให้เสร็จสมบูรณ์ ในบทความก่อนหน้านี้ KnockoutJs ไม่ได้ถูกนำมาใช้เพื่อใช้การแบ่งหน้าดังนั้นในบทความนี้ KnockoutJS + Bootstrap จะถูกนำมาใช้เพื่อใช้การแสดงการปนเปื้อนของข้อมูล
2. ใช้การ knockoutjs เพื่อใช้การปนเปื้อน
มีสองวิธีในการใช้การเพจ อย่างแรกคือการโหลดข้อมูลทั้งหมดจากนั้นแสดงข้อมูลทั้งหมดในหน้า ประการที่สองคือการโหลดข้อมูลเพียงบางส่วนในแต่ละครั้งและโหลดข้อมูลที่ตามมาใหม่ทุกครั้ง
สำหรับวิธีการทั้งสองนี้การปนเปื้อนที่ใช้โดยใช้วิธีมีดโกนโดยทั่วไปใช้วิธีที่สองในการใช้การปนเปื้อน แต่สำหรับโปรแกรมหน้าเดียวการใช้งานครั้งแรกยังมีประโยชน์เช่นกัน สำหรับข้อมูลจำนวนไม่มากวิธีการใช้งานครั้งแรกสามารถใช้งานได้เนื่องจากด้วยวิธีนี้การโหลดข้อมูลที่ตามมาจะราบรื่นมาก ดังนั้นที่นี่เราจะแนะนำวิธีการใช้งานทั้งสองนี้แยกกัน
2.1 การใช้งานการโหลดข้อมูลบางส่วนในแต่ละครั้ง
รหัสแบ็กเอนด์ที่นี่ใช้รหัสจากบทความก่อนหน้า แต่เพิ่มข้อมูลตัวอย่าง รหัสการใช้งานแบ็กเอนด์เฉพาะคือ:
/// <summary> /// Web API Service ให้บริการข้อมูลสำหรับ Web Front-end /// </summary> Public Class TaskController: Apicontroller {งานส่วนตัวแบบ readonly TaskRepository _taskRepository = taskRepository.current; ienumerable สาธารณะ <Song> getAll () {return _TaskRepository.getAll (). orderby (a => a.id); } [เส้นทาง ("api/task/getBypaged")] สาธารณะ pagedModel getall ([[fromuri] int pageindex) {const int pageize = 3; int totalCount; VAR TASKS = _TaskRepository.getAll (PageIndex, PageSize, Out TotalCount). orderby (a => a.id); var pagedata = ใหม่ pagedModel () {pageIndex = pageIndex, pagedData = tasks.tolist (), TotalCount = TotalCount, pagecount = (TotalCount+ PageSize -1) / Pagesize}; // ส่งคืนข้อมูลส่งคืน pagedata; }} /// <summary> /// ที่เก็บงานจัดเก็บการดำเนินการทั้งหมดเกี่ยวกับฐานข้อมูล /// </summary> งานระดับสาธารณะ taskrepository {#Egion Static Filed Lazy Static Private Static <TaskRepository> _TaskRepository = ใหม่ งานสาธารณะคงที่สาธารณะปัจจุบัน {รับ {return _taskrepository.value; }} #ENDEGION #REGION ฟิลด์ส่วนตัวรายการแบบอ่านอย่างเดียว <TASK> _TASKS = รายการใหม่ <SOCH> () {งานใหม่ {id = 1, name = "สร้างโปรแกรมสปา", คำอธิบาย = "SPA (เว็บแอปพลิเคชันหน้าเดียว) ข้อได้เปรียบของ SPA คือแบนด์วิดธ์จำนวนเล็กน้อยและเป็นประสบการณ์ที่ราบรื่น" datetime.parse (datetime.now.adddays (1) .toString (cultureInfo.invariantCulture))}, งานใหม่ {id = 2, name = "การเรียนรู้ที่น่าพิศวง", คำอธิบาย = "Knockoutjs เป็นห้องสมุด MVVM datetime.parse (datetime.now.adddays (2) .tostring (cultureinfo.invariantculture))}, งานใหม่ {id = 3, name = "เรียนรู้ Angularjs", คำอธิบาย = "Angularjs เป็นเฟรมเวิร์ก MVVM datetime.parse (datetime.now.adddays (3) .toString (cultureInfo.invariantCulture)), งานใหม่ {id = 4, name = "เรียนรู้เว็บไซต์ asp.net mvc", description = "Glimpse เป็นเครื่องมือทดสอบประสิทธิภาพภายใต้. รหัสของโครงการต้นฉบับและสามารถส่งออกเวลาดำเนินการของแต่ละลิงก์ของการดำเนินการรหัส ", เจ้าของ =" tonny li ", finishtime = datetime.parse (datetime.now.adddays (4) .toString (CultureInfo.invariantCulture)} งานใหม่ datetime.parse (datetime.now.adddays (5) .toString (cultureInfo.invariantCulture))}, งานใหม่ {id = 6, ชื่อ = "งานทดสอบ 2", คำอธิบาย = "งานทดสอบ 2", เจ้าของ = "Li Zhi", finishtime = " datetime.parse (datetime.now.adddays (6) .toString (cultureInfo.invariantCulture))}, งานใหม่ {id = 7, ชื่อ = "งานทดสอบ 3", คำอธิบาย = "งานทดสอบ 3", เจ้าของ = "Li Zhi", finishTime = DateTime.Parse (DateTime.now.Adddays (7) .ToString (CultureInfo.InvariantCulture))},}; #ENDREGION #REGION วิธีการสาธารณะ iEnUmerable <SOCH> GetAll () {return _TASKS; } สาธารณะ ienumerable <Sough> getAll (int pagenumber, หน้า int, out int totalCount) {var skip = (pagenumber - 1) * pagesize; var take = pagesize; TotalCount = _Tasks.count; return _tasks.skip (skip) .take (รับ); } งานสาธารณะรับ (int id) {return _tasks.find (p => p.id == id); } งานสาธารณะเพิ่ม (รายการงาน) {if (item == null) {โยน argentNullexception ใหม่ ("item"); } item.id = _tasks.count + 1; _tasks.add (รายการ); รายการส่งคืน; } โมฆะสาธารณะลบ (int id) {_tasks.removeAll (p => p.id == id); } การอัปเดตบูลสาธารณะ (รายการงาน) {if (item == null) {โยน argentNullexception ใหม่ ("item"); } var taskItem = get (item.id); if (taskItem == null) {return false; } _tasks.remove (TaskItem); _tasks.add (รายการ); กลับมาจริง; } #endregion}รหัสการใช้งาน Web Front-end:
@{viewbag.title = "index2"; layout = "~/views/thared/_layout.cshtml";} <div id = "list2"> <h2> วิธีการใช้งานครั้งที่สองของรายการ pagination-task </h2> <div> <table> ชาร์จ </th> <th> เวลาการสร้าง </th> <th> เวลาที่สมบูรณ์ </th> <th> สถานะ </th> </tr> </trem> <tbody data-bind = "foreach: pagedlist"> <tr> <td data-bind = "ข้อความ: id"> </td> <td> คำอธิบาย "> </td> <td data-bind =" ข้อความ: เจ้าของ "> </td> <td data-bind =" ข้อความ: การสร้างเวลา "> </td> <td data-bind =" text: finishtime "> </td> <td bind =" text: state "> </td> colspan = "8"> <img src = "/images/loading.gif"/> </td> </tr> </tbody> <tfoot data-bind = "ifnot: loadingstate"> <tr> <td colspan = "8"> <div> <div> data-bind = "text: pagesize"> </span> บันทึก </div> <div> <ul> <li data-bind = "css: {ปิดใช้งาน: PageIndex () === 1}"> <a href = "#" data-bind = "คลิก: ก่อนหน้า"> « </a> </li> Active: $ data.pagenumber === ($ root.pageIndex ())} "> <a href ="#"data-bind =" ข้อความ: $ data.pagenumber, คลิก: ฟังก์ชั่น () {$ root.gotopage ($ data.pagenumber); pagecount} "> <a href ="#"data-bind =" คลิก: next "> » </a> </li></ul> </div> </div> </td> </tfoot>การใช้งาน JS ที่สอดคล้องกันคือ:
// วิธีที่สองในการใช้ Paging var listViewModel2 = function () {// viewModel เอง ใช้เพื่อป้องกันความสับสนในขอบเขตเมื่อใช้สิ่งนี้โดยตรง var self = this; self.loadingState = ko.observable (จริง); self.pagesize = ko.observable (3); // data this.pagedlist = ko.observablearray (); // หมายเลขหน้าที่จะเข้าถึงนี้ pageIndex = ko.observable (1); // จำนวนทั้งหมดของหน้านี้ ko.observablearray (); // หน้าปัจจุบัน this.currengePage = ko.observable (1); self.totalcount = ko.observable (1); this.refresh = function () {// จำกัด หมายเลขหน้าคำขอภายในหมายเลขหน้าข้อมูลถ้า (self.pageindex () <1) self.pageindex (1); ถ้า self.pageindex ()> self.pagecount () sendajaxrequest ("รับ", ฟังก์ชั่น (ข้อมูล) {// ก่อนที่จะโหลดข้อมูลใหม่ลบข้อมูลต้นฉบับ self.pagedlist.removeAll (); self.allpages.removeall (); self.totalcount (data.totalcount); self.pagecount (data.pagecount); i ++) {// reload page number self.allpages.push ({pagenumber: i});} // สำหรับ ... ในคำสั่งใช้เพื่อลูปคุณสมบัติของอาร์เรย์หรือวัตถุ self.pagedlist.push (data.pageddata [i]);}}, 'getBypaged', {'pageindex': self.pageIndex ()});}; // ร้องขอหน้าแรกของข้อมูล this.first = function () {self.pageindex (1); {self.pageIndex (this.pageIndex () + 1); self.refresh ();}; // ร้องขอหน้าก่อนหน้าของข้อมูล this.previous = function () {self.pageindex (this.pageIndex () - 1); self.refresh ();}; // 1); self.refresh ();}; // เปลี่ยนเส้นทางไปยังหน้าหนึ่ง this.gotopage = ฟังก์ชั่น (ข้อมูล, เหตุการณ์) {self.pageindex (data); self.refresh ();};};}; ฟังก์ชั่น sendajaxrequest (httpmethod, callback, url, reqdata) {$ .ajax ("/api/task" + (url? "/" + url: ""), {ประเภท: httpmethod, ความสำเร็จ: callback, ข้อมูล: reqdata}; ListViewModel2 (); ViewModel.Refresh (); ถ้า ($ ('#list2'). ความยาว) ko.applyBindings (ViewModel, $ ('#list2'). รับ (0));});นี่คือความรู้เบื้องต้นเกี่ยวกับแนวคิดการใช้งานของการใช้ KnockoutJs เพื่อใช้ฟังก์ชั่นการแบ่งหน้า:
1. หลังจากโหลดหน้าแล้วให้เริ่มคำขอ AJAX เพื่อเรียกใช้บริการ REST แบบอะซิงโครนัสเพื่อขอข้อมูลส่วนหนึ่ง
2. จากนั้นแสดงข้อมูลที่ร้องขอผ่านการผูกมัดที่น่าพิศวง
3. ผูกข้อมูลเพจที่เกี่ยวข้องกับการเพจ bootstrap
4. เมื่อผู้ใช้คลิกเพื่อเปิดหน้าให้เริ่มคำขอ AJAX เพื่อเรียกใช้บริการ REST แบบอะซิงโครนัสและแสดงข้อมูลที่ร้องขอ
นี่คือความสัมพันธ์เชิงตรรกะของรหัสการโทรที่อธิบายไว้ข้างต้น คุณสามารถอ้างถึงรหัส JS ที่เกี่ยวข้องเพื่อทำความเข้าใจคำอธิบายข้างต้น ณ จุดนี้วิธีการใช้งานที่สองของเราเสร็จสมบูรณ์
2.2 โหลดข้อมูลทั้งหมดเป็นครั้งแรกจากนั้นแสดงการเพจข้อมูลทั้งหมด
ต่อไปเราจะแนะนำวิธีการใช้งานครั้งแรก ในวิธีการใช้งานนี้ผู้ใช้จะรู้สึกว่าข้อมูลกำลังโหลดเป็นครั้งแรกและพวกเขาจะไม่รู้สึกว่าการโหลดหน้าเว็บระหว่างกระบวนการเปลี่ยนหน้า สิ่งนี้จะทำให้ผู้ใช้รู้สึกราบรื่นขึ้นเมื่อมีข้อมูลไม่มากเกินไปในบางกรณี
แนวคิดการใช้งานที่เฉพาะเจาะจงคือการไม่แสดงข้อมูลที่ร้องขอทั้งหมดในหน้าเนื่องจากมีข้อมูลมากเกินไปและจะปรากฏบนหน้าในครั้งเดียวและผู้ใช้อาจตื่นตา การแสดงการเพจข้อมูลจะทำให้ผู้ใช้ดูชัดเจนยิ่งขึ้น
รหัสการใช้งานเฉพาะของ JS Front-end คือ:
var listViewModel = function () {var self = this; window.viewModel = self; self.list = ko.observablearray (); self.pagesize = ko.observable (3); self.pageindex = ko.observable (0); // หมายเลขหน้าที่จะเข้าถึง self.totalcount = ko.observable (1); // จำนวนบันทึกทั้งหมด self.loadingState = ko.observable (จริง); self.pagedList = ko.dependentobservable (ฟังก์ชัน () {var size = self.pagesize (); var start = self.pageIndex () * size; return self.list.slice (เริ่มต้น, เริ่ม + ขนาด); 1;}); self.previouspage = function () {ถ้า (self.pageindex ()> 0) {self.pageindex (self.pageindex () - 1);}}; self.nextpage = function () {ถ้า self.pageindex () 1);}}; self.allpages = ko.dependentobservable (ฟังก์ชัน () {var pages = []; สำหรับ (var i = 0; i <= self.maxPageIndex (); i ++) {pages.push ({pagenumber: (i+1)}; {self.pageIndex (ดัชนี);};}; var listViewModel = ใหม่ listViewModel (); ฟังก์ชั่น bindViewModel () {sendajaxrequest ("รับ", ฟังก์ชัน (data) ($ ('#list'). ความยาว) ko.applybindings (listviewmodel, $ ('#list'). รับ (0));}, null, null);} $ (เอกสาร). พร้อม (ฟังก์ชั่น () {bindviewmodel ();});การใช้งานหน้าส่วนหน้านั้นคล้ายกับการใช้งานก่อนหน้านี้ รหัสหน้าเฉพาะมีดังนี้:
@{viewbag.title = "index"; layout = "~/views/thared/_layout.cshtml";} <div id = "list"> <h2> รายการงาน </h2> <div> <table> <thead> <tr> เวลา </th> <th> เวลาเสร็จสิ้น </th> <th> statu </th> </tr> </tbody data-bind = "foreach: pagedlist"> <tr> <td data-bind = "text: id"> </td> <td> data-bind = "ข้อความ: เจ้าของ"> </td> <td data-bind = "ข้อความ: creationtime"> </td> <td data-bind = "text: finishtime"> </td> <td data-bind = "text: state"> </td> </tr> </tbody> src = "/images/loading.gif"/> </td> </tr> </tbody> <tfoot data-bind = "ifnot: loadingstate"> <tr> <td colspan = "8"> <div> <div> PAGESIZE "> </span> บันทึก </div> <div> <ul> <li data-bind =" css: {ปิดใช้งาน: pageindex () === 0} "> <a href ="#"data-bind =" คลิก: preheadpage "> « </a> </li> $ data.pagenumber === ($ root.pageIndex () + 1)} "> <a href ="#"data-bind =" ข้อความ: $ data.pagenumber, คลิก: ฟังก์ชั่น () {$ root.movetopage ($ data.pagenumber-1); === maxPageIndex ()} "> <a href ="#"data-bind =" คลิก: NextPage "> » </a> </li></ul> </div> </div> </td> </tr> </tfoot>3. ผลการดำเนินงาน
ถัดไปลองดูที่เอฟเฟกต์การปนเปื้อนที่ใช้โดยใช้ Knockoutjs:
4. สรุป
ณ จุดนี้เนื้อหาที่จะแนะนำในบทความนี้สิ้นสุดลง แม้ว่าเนื้อหาที่นำมาใช้ในบทความนี้ค่อนข้างง่าย แต่สำหรับเพื่อนบางคนที่ยังใหม่กับ KnockoutJs ฉันเชื่อว่าการดำเนินการตามบทความนี้จะเป็นแนวทางมากมาย ต่อไปฉันจะแบ่งปันเนื้อหาที่เกี่ยวข้องของ AngularJS กับคุณ
ข้างต้นเป็นคำอธิบายโดยละเอียดเกี่ยวกับตัวอย่างของการรวม bootstrap กับ knockoutjs เพื่อให้ได้เอฟเฟกต์การแบ่งหน้าที่บรรณาธิการแนะนำให้คุณ ฉันหวังว่ามันจะเป็นประโยชน์กับคุณ!