


Exemple détaillé de combinaison de Bootstrap et KnockoutJs pour acquérir des compétences d'effet de pagination_javascript
KnockoutJS est un framework MVVM implémenté en JavaScript. Très cool. Par exemple, une fois les éléments de données de la liste ajoutés ou supprimés, il n'est pas nécessaire d'actualiser l'intégralité du fragment de contrôle ou d'écrire du JS pour ajouter ou supprimer des nœuds par vous-même. Il vous suffit de prédéfinir le modèle et les attributs conformes à sa syntaxe. définition. En termes simples, nous devons uniquement nous concentrer sur l’accès aux données.
1.Introduction
Étant donné que le système de l'entreprise doit être révisé récemment, je prévois d'utiliser KnockoutJs pour créer l'interface Web du nouveau système. En le faisant, j'ai rencontré un problème : comment utiliser KnockoutJs pour terminer la fonction de pagination. Dans l'article précédent, nous n'avons pas introduit l'utilisation de KnockoutJs pour implémenter la pagination, donc dans cet article, nous compléterons l'utilisation de KnockoutJs+Bootstrap pour implémenter l'affichage paginé des données.
2. Utilisez KnockoutJs pour implémenter la pagination
Il existe deux façons d'implémenter la pagination. La première consiste à charger toutes les données, puis à afficher toutes les données dans des pages ; la seconde consiste à charger uniquement une partie des données à chaque fois et à recharger les éléments suivants pour chaque requête. données.
Pour ces deux méthodes, la pagination implémentée à l'aide de la méthode Razor utilisera généralement la deuxième méthode pour implémenter la pagination. Cependant, pour les programmes à page unique, la première méthode d'implémentation a également ses avantages pour des quantités de données peu importantes. est complètement La première méthode de mise en œuvre peut être utilisée, car dans ce cas, l'expérience utilisateur du chargement ultérieur des données sera très fluide. Ces deux méthodes de mise en œuvre seront donc présentées ici.
2.1 Mise en place du chargement des données partielles à chaque fois
Le code backend ici utilise le code de l'article précédent, avec juste quelques exemples de données supplémentaires ajoutées. Le code d'implémentation spécifique du backend est :
/// <summary> /// Web API 服务,为Web前端提供数据服务 /// </summary> public class TaskController : ApiController { private readonly TaskRepository _taskRepository = TaskRepository.Current; public IEnumerable<Task> GetAll() { return _taskRepository.GetAll().OrderBy(a => a.Id); } [Route("api/task/GetByPaged")] public PagedModel GetAll([FromUri]int pageIndex) { const int pageSize = 3; int totalCount; var tasks = _taskRepository.GetAll(pageIndex, pageSize, out totalCount).OrderBy(a => a.Id); var pageData = new PagedModel() { PageIndex = pageIndex, PagedData = tasks.ToList(), TotalCount = totalCount, PageCount = (totalCount+ pageSize -1) / pageSize }; //返回数据 return pageData; } } /// <summary> /// 任务仓储,封装了所有关于数据库的操作 /// </summary> public class TaskRepository { #region Static Filed private static Lazy<TaskRepository> _taskRepository = new Lazy<TaskRepository>(() => new TaskRepository()); public static TaskRepository Current { get { return _taskRepository.Value; } } #endregion #region Fields private readonly List<Task> _tasks = new List<Task>() { new Task { Id =1, Name = "创建一个SPA程序", Description = "SPA(single page web application),SPA的优势就是少量带宽,平滑体验", Owner = "Learning hard", FinishTime = DateTime.Parse(DateTime.Now.AddDays(1).ToString(CultureInfo.InvariantCulture)) }, new Task { Id =2, Name = "学习KnockoutJs", Description = "KnockoutJs是一个MVVM类库,支持双向绑定", Owner = "Tommy Li", FinishTime = DateTime.Parse(DateTime.Now.AddDays(2).ToString(CultureInfo.InvariantCulture)) }, new Task { Id =3, Name = "学习AngularJS", Description = "AngularJs是MVVM框架,集MVVM和MVC与一体。", Owner = "李志", FinishTime = DateTime.Parse(DateTime.Now.AddDays(3).ToString(CultureInfo.InvariantCulture)) }, new Task { Id =4, Name = "学习ASP.NET MVC网站", Description = "Glimpse是一款.NET下的性能测试工具,支持asp.net 、asp.net mvc, EF等等,优势在于,不需要修改原项目任何代码,且能输出代码执行各个环节的执行时间", Owner = "Tonny Li", FinishTime = DateTime.Parse(DateTime.Now.AddDays(4).ToString(CultureInfo.InvariantCulture)) }, new Task { Id =5, Name = "测试任务1", Description = "测试任务1", Owner = "李志", FinishTime = DateTime.Parse(DateTime.Now.AddDays(5).ToString(CultureInfo.InvariantCulture)) }, new Task { Id =6, Name = "测试任务2", Description = "测试任务2", Owner = "李志", FinishTime = DateTime.Parse(DateTime.Now.AddDays(6).ToString(CultureInfo.InvariantCulture)) }, new Task { Id =7, Name = "测试任务3", Description = "测试任务3", Owner = "李志", FinishTime = DateTime.Parse(DateTime.Now.AddDays(7).ToString(CultureInfo.InvariantCulture)) }, }; #endregion #region Public Methods public IEnumerable<Task> GetAll() { return _tasks; } public IEnumerable<Task> GetAll(int pageNumber, int pageSize, out int totalCount) { var skip = (pageNumber - 1) * pageSize; var take = pageSize; totalCount = _tasks.Count; return _tasks.Skip(skip).Take(take); } public Task Get(int id) { return _tasks.Find(p => p.Id == id); } public Task Add(Task item) { if (item == null) { throw new ArgumentNullException("item"); } item.Id = _tasks.Count + 1; _tasks.Add(item); return item; } public void Remove(int id) { _tasks.RemoveAll(p => p.Id == id); } public bool Update(Task item) { if (item == null) { throw new ArgumentNullException("item"); } var taskItem = Get(item.Id); if (taskItem == null) { return false; } _tasks.Remove(taskItem); _tasks.Add(item); return true; } #endregion }
Code d'implémentation du front-end Web :
@{ ViewBag.Title = "Index2"; Layout = "~/Views/Shared/_Layout.cshtml"; } <div id="list2"> <h2>分页第二种实现方式——任务列表</h2> <div class="table-responsive"> <table class="table table-striped"> <thead> <tr> <th>编号</th> <th>名称</th> <th>描述</th> <th>负责人</th> <th>创建时间</th> <th>完成时间</th> <th>状态</th> </tr> </thead> <tbody data-bind="foreach:pagedList"> <tr> <td data-bind="text: id"></td> <td><a data-bind="text: name"></a></td> <td data-bind="text: description"></td> <td data-bind="text: owner"></td> <td data-bind="text: creationTime"></td> <td data-bind="text: finishTime"></td> <td data-bind="text: state"></td> </tr> </tbody> <tbody data-bind="if: loadingState"> <tr> <td colspan="8" class="text-center"> <img width="60" src="/images/loading.gif" /> </td> </tr> </tbody> <tfoot data-bind="ifnot:loadingState"> <tr> <td colspan="8"> <div class="pull-right"> <div>总共有<span data-bind="text: totalCount"></span>条记录, 每页显示:<span data-bind="text: pageSize"></span>条</div> <div> <ul class="pagination"> <li data-bind="css: { disabled: pageIndex() === 1 }"><a href="#" data-bind="click: previous">«</a></li> </ul> <ul data-bind="foreach: allPages" class="pagination"> <li data-bind="css: { active: $data.pageNumber === ($root.pageIndex()) }"><a href="#" data-bind="text: $data.pageNumber, click: function() { $root.gotoPage($data.pageNumber); }"></a></li> </ul> <ul class="pagination"><li data-bind="css: { disabled: pageIndex() === pageCount }"><a href="#" data-bind="click: next">»</a></li></ul> </div> </div> </td> </tr> </tfoot> </table> </div> </div>
L'implémentation Js correspondante est :
// 实现分页的第二种方式 var ListViewModel2 = function() { //viewModel本身。用来防止直接使用this的时候作用域混乱 var self = this; self.loadingState = ko.observable(true); self.pageSize = ko.observable(3); //数据 this.pagedList = ko.observableArray(); //要访问的页码 this.pageIndex = ko.observable(1); //总页数 this.pageCount = ko.observable(1); //页码数 this.allPages = ko.observableArray(); //当前页 this.currengePage = ko.observable(1); self.totalCount = ko.observable(1); this.refresh = function() { //限制请求页码在该数据页码范围内 if (self.pageIndex() < 1) self.pageIndex(1); if (self.pageIndex() > self.pageCount()) { self.pageIndex(self.pageCount()); } //post异步加载数据 sendAjaxRequest("GET", function (data) { // 加载新的数据前,先移除原先的数据 self.pagedList.removeAll(); self.allPages.removeAll(); self.totalCount(data.totalCount); self.pageCount(data.pageCount); self.loadingState(false); for (var i = 1; i <= data.pageCount; i++) { //装填页码 self.allPages.push({ pageNumber: i }); } //for...in 语句用于对数组或者对象的属性进行循环操作。 //for ... in 循环中的代码每执行一次,就会对数组的元素或者对象的属性进行一次操作。 for (var i in data.pagedData) { //装填数据 self.pagedList.push(data.pagedData[i]); } }, 'GetByPaged', { 'pageIndex': self.pageIndex() }); }; //请求第一页数据 this.first = function() { self.pageIndex(1); self.refresh(); }; //请求下一页数据 this.next = function() { self.pageIndex(this.pageIndex() + 1); self.refresh(); }; //请求先前一页数据 this.previous = function() { self.pageIndex(this.pageIndex() - 1); self.refresh(); }; //请求最后一页数据 this.last = function() { self.pageIndex(this.pageCount() - 1); self.refresh(); }; //跳转到某页 this.gotoPage = function (data, event) { self.pageIndex(data); self.refresh(); }; }; function sendAjaxRequest(httpMethod, callback, url, reqData) { $.ajax("/api/task" + (url ? "/" + url : ""), { type: httpMethod, success: callback, data: reqData }); } $(document).ready(function () { var viewModel = new ListViewModel2(); viewModel.refresh(); if ($('#list2').length) ko.applyBindings(viewModel, $('#list2').get(0)); });
Voici une introduction à l'idée d'implémentation consistant à utiliser KnockoutJs pour implémenter la fonction de pagination :
1. Une fois la page chargée, lancez une requête Ajax pour appeler de manière asynchrone le service REST pour demander certaines données.
2. Affichez ensuite les données demandées via la liaison KnockoutJs.
3. Liez les informations de pagination correspondantes à la pagination Bootstrap
4. Lorsque l'utilisateur clique pour tourner la page, lancez une requête Ajax pour appeler de manière asynchrone le service Rest pour demander des données, puis affichez les données demandées.
Ce qui précède est la relation logique d'appel du code décrit ci-dessus. Vous pouvez vous référer au code JS correspondant pour comprendre la description ci-dessus. À ce stade, notre deuxième méthode de mise en œuvre est terminée.
2.2 Charger toutes les données pour la première fois, puis afficher toutes les données dans les pages
Ensuite, nous introduisons la première méthode d'implémentation.Avec cette méthode d'implémentation, l'utilisateur sentira seulement que les données se chargent pour la première fois, et ne sentira pas que la page se charge pendant le processus de rotation de page. , pour certains Lorsque les données elles-mêmes ne sont pas trop nombreuses, l'expérience utilisateur est plus fluide.
L'idée spécifique de l'implémentation est de ne pas afficher toutes les données demandées sur la page, car il y a trop de données et l'utilisateur peut être ébloui si elles sont affichées d'un seul coup sur la page. L'affichage des données dans des pages les rendra plus claires pour les utilisateurs.
Le code d'implémentation spécifique du Web front-end Js est :
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(true); self.pagedList = ko.dependentObservable(function () { var size = self.pageSize(); var start = self.pageIndex() * size; return self.list.slice(start, start + size); }); self.maxPageIndex = ko.dependentObservable(function () { return Math.ceil(self.list().length / self.pageSize()) - 1; }); self.previousPage = function () { if (self.pageIndex() > 0) { self.pageIndex(self.pageIndex() - 1); } }; self.nextPage = function () { if (self.pageIndex() < self.maxPageIndex()) { self.pageIndex(self.pageIndex() + 1); } }; self.allPages = ko.dependentObservable(function () { var pages = []; for (var i = 0; i <= self.maxPageIndex() ; i++) { pages.push({ pageNumber: (i + 1) }); } return pages; }); self.moveToPage = function (index) { self.pageIndex(index); }; }; var listViewModel = new ListViewModel(); function bindViewModel() { sendAjaxRequest("GET", function (data) { listViewModel.loadingState(false); listViewModel.list(data); listViewModel.totalCount(data.length); if ($('#list').length) ko.applyBindings(listViewModel, $('#list').get(0)); }, null, null); } $(document).ready(function () { bindViewModel(); });
La mise en œuvre de sa page front-end est similaire à la mise en œuvre précédente. Le code spécifique de la page est le suivant :
@{ ViewBag.Title = "Index"; Layout = "~/Views/Shared/_Layout.cshtml"; } <div id="list"> <h2>任务列表</h2> <div class="table-responsive"> <table class="table table-striped"> <thead> <tr> <th>编号</th> <th>名称</th> <th>描述</th> <th>负责人</th> <th>创建时间</th> <th>完成时间</th> <th>状态</th> </tr> </thead> <tbody data-bind="foreach:pagedList"> <tr> <td data-bind="text: id"></td> <td><a data-bind="text: name"></a></td> <td data-bind="text: description"></td> <td data-bind="text: owner"></td> <td data-bind="text: creationTime"></td> <td data-bind="text: finishTime"></td> <td data-bind="text: state"></td> </tr> </tbody> <tbody data-bind="if:loadingState"> <tr> <td colspan="8" class="text-center"> <img width="60" src="/images/loading.gif" /> </td> </tr> </tbody> <tfoot data-bind="ifnot:loadingState"> <tr> <td colspan="8"> <div class="pull-right"> <div>总共有<span data-bind="text: totalCount"></span>条记录, 每页显示:<span data-bind="text: pageSize"></span>条</div> <div> <ul class="pagination"> <li data-bind="css: { disabled: pageIndex() === 0 }"><a href="#" data-bind="click: previousPage">«</a></li> </ul> <ul data-bind="foreach: allPages" class="pagination"> <li data-bind="css: { active: $data.pageNumber === ($root.pageIndex() + 1) }"><a href="#" data-bind="text: $data.pageNumber, click: function() { $root.moveToPage($data.pageNumber-1); }"></a></li> </ul> <ul class="pagination"><li data-bind="css: { disabled: pageIndex() === maxPageIndex() }"><a href="#" data-bind="click: nextPage">»</a></li></ul> </div> </div> </td> </tr> </tfoot> </table> </div> </div>
3. Effet d'opération
Ensuite, jetons un coup d'œil à l'effet de pagination obtenu avec KnockoutJs :
4.Résumé
À ce stade, le contenu à présenter dans cet article se termine. Bien que le contenu implémenté dans cet article soit relativement simple, pour certains amis qui sont nouveaux sur KnockoutJs, je pense que la mise en œuvre de cet article sera très utile. . Ensuite, je partagerai avec vous le contenu pertinent d'AngularJs.
Ce qui précède est l'explication détaillée de l'exemple de combinaison de Bootstrap et KnockoutJs pour obtenir l'effet de pagination introduit par l'éditeur. J'espère que cela sera utile à tout le monde !

Outils d'IA chauds

Undresser.AI Undress
Application basée sur l'IA pour créer des photos de nu réalistes

AI Clothes Remover
Outil d'IA en ligne pour supprimer les vêtements des photos.

Undress AI Tool
Images de déshabillage gratuites

Clothoff.io
Dissolvant de vêtements AI

AI Hentai Generator
Générez AI Hentai gratuitement.

Article chaud

Outils chauds

Bloc-notes++7.3.1
Éditeur de code facile à utiliser et gratuit

SublimeText3 version chinoise
Version chinoise, très simple à utiliser

Envoyer Studio 13.0.1
Puissant environnement de développement intégré PHP

Dreamweaver CS6
Outils de développement Web visuel

SublimeText3 version Mac
Logiciel d'édition de code au niveau de Dieu (SublimeText3)

L'article discute de la création, de la publication et du maintien des bibliothèques JavaScript, en se concentrant sur la planification, le développement, les tests, la documentation et les stratégies de promotion.

L'article traite des stratégies pour optimiser les performances JavaScript dans les navigateurs, en nous concentrant sur la réduction du temps d'exécution et la minimisation de l'impact sur la vitesse de chargement de la page.

Des questions et des solutions fréquemment posées pour l'impression de billets thermiques frontaux pour le développement frontal, l'impression de billets est une exigence commune. Cependant, de nombreux développeurs mettent en œuvre ...

L'article traite du débogage efficace de JavaScript à l'aide d'outils de développeur de navigateur, de se concentrer sur la définition des points d'arrêt, de l'utilisation de la console et d'analyser les performances.

L'article explique comment utiliser les cartes source pour déboguer JavaScript minifiée en le mappant au code d'origine. Il discute de l'activation des cartes source, de la définition de points d'arrêt et de l'utilisation d'outils comme Chrome Devtools et WebPack.

Cet article explore une utilisation efficace du cadre de collections de Java. Il met l'accent sur le choix des collections appropriées (liste, set, map, file d'attente) en fonction de la structure des données, des besoins en performances et de la sécurité des threads. Optimisation de l'utilisation de la collection grâce à

Une fois que vous avez maîtrisé le didacticiel TypeScript de niveau d'entrée, vous devriez être en mesure d'écrire votre propre code dans un IDE qui prend en charge TypeScript et de le compiler en JavaScript. Ce tutoriel plongera dans divers types de données dans TypeScript. JavaScript a sept types de données: null, non défini, booléen, numéro, chaîne, symbole (introduit par ES6) et objet. TypeScript définit plus de types sur cette base, et ce tutoriel les couvrira tous en détail. Type de données nuls Comme javascript, null en typeScript

Ce tutoriel expliquera comment créer des graphiques à tarte, anneaux et bulles à l'aide de chart.js. Auparavant, nous avons appris quatre types de graphiques de graphique. Créer des graphiques à tarte et à anneaux Les graphiques à tarte et les graphiques d'anneaux sont idéaux pour montrer les proportions d'un tout divisé en différentes parties. Par exemple, un graphique à secteurs peut être utilisé pour montrer le pourcentage de lions mâles, de lions féminins et de jeunes lions dans un safari, ou le pourcentage de votes que différents candidats reçoivent lors des élections. Les graphiques à tarte ne conviennent que pour comparer des paramètres ou des ensembles de données uniques. Il convient de noter que le graphique à tarte ne peut pas dessiner des entités avec une valeur nulle car l'angle du ventilateur dans le graphique à tarte dépend de la taille numérique du point de données. Cela signifie toute entité avec une proportion nulle
