使用异步controller与jQuery实现卷帘式分页


Posted in jQuery onJune 18, 2019

问题

今天很多网站与数据库交互。如果您的网站接收大量的流量,SQL查询来检索数据,是相当激烈的。更重要的是因为普通用户点击一个在15秒内到达您的网站的链接, 检索和生成内容的工作可能是不必要的,尤其是当内容是“地域折叠”(不滚动是不可见的)。为了帮助解决这个问题,内容将被“按需”载入。足够的内容将被载入,使页面感觉起来是随用户向下滚动阅读递增的,更多的内容将在不影响用户体验的场景下填充。

解决方案

使用异步controller与jQuery按需加载内容,当用户开始通过网站的内容滚动时进一步加载内容。

讨论

异步controller可能在许多MVC应用中未充分利用。最有可能的是因为人们不知道他们,更重要的是,不知道何时使用它们。以下是摘录见MSDN网站:

“在应用中,线程饥饿可能会发生,您可以配置action 异步处理。异步请求和同步请求过程需要相同的时间例如,如果一个请求,使得网络调用需要两秒钟来完成的,请求需要两秒钟,无论是执行同步或异步。然而,在一个异步调用,当服务器响应等待它的第一次请求时完成时他响应其他的请求没有被阻塞。因此,当有许多请求调用长时间运行的操作时,异步请求会防止请求排队。“

在这个例子里,异步请求是完美的解决方案。因为他会让IIS服务器有能力去处理更多重要的请求,比如一个新的用户第一次访问网站。其中,加载用户点播内容是不太重要,因为大多数人甚至不关注被加载额外的内容。在一个典型的社交网站,大多数活动可能包含用户的意见。在以前的秘方中,创建了一个评论的功能。

在这个例子中,将更新网站的网页,列出最近的评论。足够的评论会被显示,所以会出现滚动条。一旦用户开始滚动,一个Ajax请求异步controller将检索其他评论。

首先Home/Index view 需要更新去显示最近的评论。为了提供一些评论的上下文内容,关于书的基础详情也将被显示为导航到图书的链接。所以这个view将简单的调用view 中的render function会在下边创建:

@model IEnumerable<MvcApplication.Models.BookComment>
@{
ViewBag.Title = "Home Page";
}
<h2>@ViewBag.Message</h2>
<p>
To learn more about ASP.NET MVC visit <a href="http://asp.net/mvc" rel="external nofollow" title="ASP.NET MVC Website">
http://asp.net/mvc</a>.
</p>
<script type="text/javascript">
var lastY = 0;
var currentY = 0;
var page = 1;
var maxPages = @ViewBag.maxPages;
$(window).scroll(function () {
if (page < maxPages) {
currentY = $(window).scrollTop();
if (currentY - lastY > 200 * (page - 1)) {
lastY = currentY;
page++;
$.get('CommentFeed/Comments?page=' + page,
function(data) {
$('#comments').append(data);
});
}
}
});
</script>
<div id="comments">
<h2>
Recent Comments</h2>
@Html.Partial("../CommentFeed/Comments", Model)
</div>

在上面的例子,执行滚动窗口时也有一些比较复杂的JavaScript代码会执行。一些全局JavaScript变量被定义去保持监控当前的“Y”滚动的位置,最后的“Y”滚动位置和当前被检索的页面。当窗口的scrollTop位置减去最后的滚动位置是大于一个具体的数字,通过Ajax检索新书评论并附加到评论列表。

你将根据你自己的网站去根据矫正那个具体的数字,基于内容的高度,要确保新的内容总是要提前检索。

下一步,HomeController需要更新检索图书评论列表。 评论在降序排序,以确保最新的创建日期评论首先显示。为了防止激烈的数据库负载,全部评论将减少到一个小数目。这应该根据你的网站去调节,以确保有足够的内容,导致滚动。在下面的例子,建议被限制在3。分页的最大数也取决于评论总数于除以3。一旦最大的评论数已经返回,最大分页数是用来防止进一步的Ajax调用。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Globalization;
using System.Data.Entity;
using MvcApplication.Models;
namespace MvcApplication.Controllers
{
public class HomeController : Controller
{
private BookDBContext db = new BookDBContext();
public ActionResult Index()
{
ViewBag.Message = "Welcome to ASP.NET MVC!";
// Get our recent comments
var bookcomments = db.BookComments.Include(b => b.Book).OrderByDescending(b => b.Created).Take(3);
var count = db.BookComments.Count();
ViewBag.maxPages = count / 3 + 1;
return View(bookcomments);
}
public ActionResult ChangeLanguage(string language)
{
Session["CurrentLanguage"] = new CultureInfo(language);
return Redirect("Index");
}
public ActionResult About()
{
return View();
}
public ActionResult MobileTest()
{
return View();
}
public ActionResult MobileTest2()
{
return View();
}
}
}

同样的功能需要被复制到一个新的异步controller。控制器文件夹选中,右键单击并选择“添加→控制器。新
控制器将被命名为CommentFeedController。该控制器不需要脚手架模板功能,下拉,选择空
控制器,然后按添加。

这个控制器会看起来与一个典型的控制器稍有不同。使用异步控制器,一个view将分成两个函数。第一个函数执行的异步
请求(例如,检索的view)。第二个函数接收结果,异步调用和返回或显示的结果。

提示:在下面的例子,呈现局部视图。在某些应用中,它可能是有益的,以减少网络流量,返回一个JSON结果,让JavaScript代码处理与显示。但是,要简化这个例子,重点放在异步控制器,前者将用于返回一个partial view。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using MvcApplication.Models;
using System.Data.Entity;
namespace MvcApplication.Controllers
{
public class CommentFeedController : AsyncController
{
private BookDBContext db = new BookDBContext();
public void CommentsAsync(int page)
{
AsyncManager.OutstandingOperations.Increment();
AsyncManager.Sync(() =>
{
var bookcomments = db.BookComments.Include(
b => b.Book).OrderByDescending(b =>
b.Created).Skip(page * 3).Take(3);
AsyncManager.Parameters["bookcomments"] =
bookcomments;
AsyncManager.OutstandingOperations.Decrement();
});
}
public ActionResult CommentsCompleted(
IEnumerable<BookComment> bookcomments)
{
return PartialView(bookcomments);
}
}
}

第一个 函数,CommentsAsync,接收从javascript传入的当前页面,并且用这个值去检索接下来的三个评论。然后通过异步方法,检索评论并且传递一个变量到第二个函数。最终的事是执行AsyncManager.OutstandingOperations.Decrement()方法。OutstandingOperations(未解决操作)的increment(递增)和decrement(递减)的匹配是很重要的。否则,当他们不匹配时,sync manager 将取消请求,这可以组织永不休止的请求。

第二个函数接收book comments 并且返回一个partial view。这和Home/Index view一样。在这个过程的最后一个步骤是创建partial view。右击文件夹,添加新文件夹。这个文件夹应该命名为CommentFeed去匹配controller的名字。选择这个文件夹,右击,点Add→View 命名为Comments-----在添加它之前确定去检查Partial view。

@model IEnumerable<MvcApplication.Models.BookComment>
@foreach (var item in Model) {
<h3><a href="@Url.Action(" rel="external nofollow" Details", "Books", new {ID=item.Book.ID } )">
@Html.DisplayFor(modelItem => item.Book.Title)
</a></h3>
<h4>Comment Posted: @Html.DisplayFor(
modelItem => item.Created)</h4>
<p>@MvcHtmlString.Create(Html.Encode(item.Comment).Replace(
Environment.NewLine, "<br />"))</p>
}

上边的view遍历comments,并首先显示书的标题和详细信息页面的链接,然后创建评论的日期,最后创建comment本身。由于View里可能包含换行符,用<br/>替代每个Evironment.NewLine去匹配评论输入间距。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

jQuery 相关文章推荐
纯jQuery实现前端分页功能
Mar 23 jQuery
JavaScript使用链式方法封装jQuery中CSS()方法示例
Apr 07 jQuery
vue中如何引入jQuery和Bootstrap
Apr 10 jQuery
JQuery form表单提交前验证单选框是否选中、删除记录时验证经验总结(整理)
Jun 09 jQuery
jquery DataTable实现前后台动态分页
Jun 17 jQuery
用户管理的设计_jquery的ajax实现二级联动效果
Jul 13 jQuery
jQuery ajax调用webservice注意事项
Oct 08 jQuery
jQuery实现判断上传图片类型和大小的方法示例
Apr 11 jQuery
jQuery中元素选择器(element)简单用法示例
May 14 jQuery
使用jquery DataTable和ajax向页面显示数据列表的方法
Aug 09 jQuery
jQuery插件实现非常实用的tab栏切换功能【案例】
Feb 18 jQuery
jQuery动态生成的元素绑定事件操作实例分析
May 04 jQuery
使用jQuery mobile NuGet让你的网站在移动设备上同样精彩
Jun 18 #jQuery
如何使用CSS3和JQuery easing 插件制作绚丽菜单
Jun 18 #jQuery
如何用webpack4.0撸单页/多页脚手架 (jquery, react, vue, typescript)
Jun 18 #jQuery
通过JQuery,JQueryUI和Jsplumb实现拖拽模块
Jun 18 #jQuery
如何使用CSS3+JQuery实现悬浮墙式菜单
Jun 18 #jQuery
jquery中为什么能用$操作
Jun 18 #jQuery
js/jQuery实现全选效果
Jun 17 #jQuery
You might like
简单的过滤字符串中的HTML标记
2006/12/25 PHP
用PHP制作的意见反馈表源码
2007/03/11 PHP
php错误、异常处理机制(补充)
2012/05/07 PHP
php中文繁体和简体相互转换的方法
2015/03/21 PHP
php如何连接sql server
2015/10/16 PHP
PHP抓取及分析网页的方法详解
2016/04/26 PHP
PHP弱类型语言中类型判断操作实例详解
2017/08/10 PHP
thinkphp ajaxfileupload实现异步上传图片的示例
2017/08/28 PHP
PHP使用正则表达式实现过滤非法字符串功能示例
2018/06/04 PHP
Laravel中为什么不使用blpop取队列详析
2018/08/01 PHP
event对象的方法 兼容多浏览器
2009/06/27 Javascript
一个级联菜单代码学习及removeClass与addClass的应用
2013/01/24 Javascript
javascript中全局对象的parseInt()方法使用介绍
2013/12/19 Javascript
我的NodeJs学习小结(一)
2014/07/06 NodeJs
常用DOM整理
2015/06/16 Javascript
jquery读写cookie操作实例分析
2015/12/24 Javascript
原生JS实现的简单轮播图功能【适合新手】
2018/08/17 Javascript
Vue表情输入组件 微信face表情组件
2019/02/11 Javascript
vue draggable resizable gorkys与v-chart使用与总结
2019/09/05 Javascript
javascript 关于赋值、浅拷贝、深拷贝的个人理解
2019/11/01 Javascript
JS遍历树层级关系实现原理解析
2020/08/31 Javascript
vue项目如何监听localStorage或sessionStorage的变化
2021/01/04 Vue.js
python两种遍历字典(dict)的方法比较
2014/05/29 Python
Python中音频处理库pydub的使用教程
2017/06/07 Python
python模拟表单提交登录图书馆
2018/04/27 Python
python实现简单成绩录入系统
2019/09/19 Python
keras实现VGG16方式(预测一张图片)
2020/07/07 Python
python 实现Requests发送带cookies的请求
2021/02/08 Python
JENNIFER BEHR官网:各种耳环和发饰
2020/06/07 全球购物
.NET里面如何取得当前的屏幕分辨率
2012/12/06 面试题
十佳大学生事迹材料
2014/01/29 职场文书
《白鹅》教学反思
2014/04/13 职场文书
硕士论文致谢范文
2015/05/14 职场文书
观看《信仰》心得体会
2016/01/15 职场文书
导游词之无锡唐城
2019/12/12 职场文书
教你用Java在个人电脑上实现微信扫码支付
2021/06/13 Java/Android