好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

PagedList+Ajax+JsRender

PagedList+Ajax+JsRender

  昨天在 ASP.NET MVC利用PagedList分页(一) 的最后一节提到,一个好的用户体验绝对不可能是点击下一页后刷新页面,所以今天来说说利用Ajax+PagedList实现无刷新(个人绝对局部刷新更准确些)的分页。其实在PagedList.Mvc中早已经为我们提供好了Ajax分页的各种东东,但是这里我要自己写下。

   实现思想:

     1、客户端发送Ajax请求。2、服务器端响应请求并将响应结果回传给客户端。3、客户端接收响应结果并进行数据绑定。

   实现方案:

  大多数人都知道这个思想,但是面对一个陌生的环境,我不得不理一下思路然后再讨论实现方案:1、利用Jquery Ajax发送分页请求。2、进行数据划分并利用SataticPagedList<T>(我个人比较喜欢这个,也可以用ToPagedList)绑定。3、利用Jquery Ajax接收数据并进行数据绑定。 ok,实现方案出炉,下面直接上代码:

 //  View:Views/Person/Ajax 
<link href= "  /Content/PagedList.css  "  type= "  text/css  "  rel= "  Stylesheet  "  /> 
......
 <script type= "  text/javascript  "  src= "  /Scripts/jquery-1.5.1.js  " ></script>
<script type= "  text/javascript  " > 
    $(function () {
        getPersonByAjax(  1  );
    });
   //Ajax请求
       var  getPersonByAjax =  function (pageNumber) {
        $.ajax({
            url:   "  /Person/AjaxPage?page=  "  +  pageNumber,
            type:   "  POST  "  ,
            dataType:   "  json  "  ,
            success: function (data) {
                  //接收数据(data)并  绑定 
                 var  html =  ""  ;
                $.each(data.persons, function (i, item) {
                    html  +=  "  <tr><td>  "  + item.FirstName +  "  </td><td>  "  + item.LastName +
                         "  </td><td><a href='/Person/Edit/  "  + item.PersonID +  "  '>Edit</a> | <a href='/Person/Details/  "  + 
                        item.PersonID  +  "  '>Details</a> | <a href='/Person/Delete/  "  + item.PersonID +  "  '>Delete</a></td></tr>  "  ;
                });
                $(  "  #personList  "  ).html(html);
            },
            error: function (result) {
                alert(result.statusText);
            },
            complete: function (jqXHR) {
                jqXHR  =  null  ;
            }
        });
    }
 </script>

 //  Controller:PersonController 

//响应Ajax请求 public ActionResult AjaxPage( int ? page) { int pageIndex = page ?? 1 ; int pageSize = 2 ; int totalCount = 0 ; var persons = GetPerson(pageIndex, pageSize, ref totalCount); var personsAsIPageList = new StaticPagedList<Person> (persons, pageIndex, pageSize, totalCount); return Json( new { persons = personsAsIPageList},JsonRequestBehavior.AllowGet); } public List<Person> GetPerson( int pageIndex, int pageSize, ref int totalCount) { var persons = ( from p in db.Persons orderby p.PersonID descending select p).Skip((pageIndex - 1 ) * pageSize).Take(pageSize); totalCount = db.Persons.Count(); return persons.ToList(); }
(注:这里运用到了Json在服务器和客户端之间传递的知识额...我非常喜欢Json接收强类型对象,后头有机会慢慢谈下。)

   在写“接收数据(data)并绑定之前”我还在天真的想,personAdIPagedList不会回吧HasPreviousPage、HasNextNextPage也传递过来呢?于是我用Fillder服务器端到底会传递什么回来,结果如下:

  挂了,貌似他至传回了persons的json数据,那分页咋办呢?原来在IPagedList<T>中有个GetMetaData,他会返回一个PagedListMetaData对象,在这里进行了分页导航相关属性的分装:

   添加分页导航

  g ood,这下我可以完善我的代码了。 如下:

 public  ActionResult AjaxPage( int ?  page)
{
      int  pageIndex = page ??  1  ;
      int  pageSize =  2  ;
      int  totalCount =  0  ;
      var  persons = GetPerson(pageIndex, pageSize,  ref   totalCount);
      var  personsAsIPageList =  new  StaticPagedList<Person> (persons, pageIndex, pageSize, totalCount);
       return  Json( new  { persons = personsAsIPageList,   pager =      personsAsIPageList.GetMetaData()   }, JsonRequestBehavior.AllowGet);
} 

   可以看到这里PagedList传回了所有的分页信息。所以可以做分页导航了:

 //  创建分页导航 
                 var  pager =  data.pager;
                html  =  ""  ;
                  if   (pager.HasPreviousPage) {
                    html  +=  "  <a href='#' onclick='getPersonByAjax(  "  + (pager.PageNumber -  1 ) +  "  );return false;'>&lt;&lt;</a> <a href='#' onclick='getPersonByAjax(1);return false;'>&lt; Prev</a>  "  ;
                }
                  else   {
                    html  +=  "  &lt;&lt; &lt; Prev  "  ;
                }
                html  +=  "   "  ;
                  if   (pager.HasNextPage) {
                    html  +=  "  <a href='#' onclick='getPersonByAjax(  "  + (pager.PageNumber +  1 ) +  "  );return false;'>Next &gt;</a> <a href='#' onclick='getPersonByAjax(  "  + pager.PageCount +  "  );return false;'>&gt;&gt;</a>  "  ;
                }
                  else   {
                    html  +=  "  Next &gt; &gt;&gt;  "  ;
                }
                $(  "  #pager  " ).html(html);

    将上面代码插入success中,分页就创建好了。当我正在高兴的时候我大概忘记了刚刚做字符串拼接的辛苦。冷静下来后我和PagedList提供的实例(好像忘了给地址,给一个: https://github.com/TroyGoode/PagedList )进行了对比,对比结果是我无比蛋疼。在其提供实例中用到了jquery.tmpl.js,原来我们真的不用做如此多的字符处啊拼接工作。

   优化绑定

  jquery. tmpl .js是一个模板插件,能够用对象或数据等对模板(包含html、css等标签和绑定表达式。)进行渲染,举个例子:"<li class='XXX' id='liTemplate'>${name}</li>"这就是一个模板,包含html、css和绑定表达式(${name}), 现在我们只需利用:$.template("templateName",$('# liTemplate ').html());$.tmpl( templateName ,list).appendTo('#liContainer');将模板渲染(tmpl)然后插入容器(liContainer)展示即可。第一句将liTemplate标记为一个模板,名称为 templateName 。第二句利用list将 templateName进行渲染,然后插入到liContainer中。list可以使一个数据,也可以是一个对象,例如:var  list = {"name":"hello world","name":"heihei"}。总之,tmpl可以让我们不用在写字符串连接,它的可见性太差了,极其难维护。同时,利用tmpl需要三要素:模板,容器,数据。利用数据渲染模板,将结果插入容器中我们便可以轻松完成js中的数据绑定。

  事后,我在其官网( https://github.com/jquery/jquery-tmpl )上查阅了相关治疗,发现jquey.tmpl还停留在测试期,并且不再提供升级,被jquery放弃了。。。下一代jquery 模板由JsRender和JsViews承担,相关资料可以去官网上看(JsRender: https://github.com/BorisMoore/jsrender ;JsViews: https://github.com/BorisMoore/jsview s )。JsRedner和tmpl差不多,但是据介绍说,JsRender的渲染速度比tmpl快很多很多,到底快多少我也不知道,而且给我的直观感受就是,JsRedner比tmpl的语法简单的写。。这个我喜欢。JsRender强调纯粹的基于字符串的渲染,而且可以不需要dom和jquery的支持,上面我们可以看到tmpl是需要的: $.template("templateName",$('# liTemplate ').html()); ;而JsViews则是建立在JsRender上更高层次的封装,他强调建立交互式的数据驱动视图,具体的貌似我目前还不是很了解。

  ok,废话少说,关于JsRender相关的东东在后头我在慢慢整理出来,下面看看它在项目中间的运用,当时我真的大吃一惊,修改 View:Views/Person/Ajax代码如下:

 //  View:Views/Person/Ajax 
 ......
  //  绑定模板 
<script type= "  text/x-jsrender  "  id= "  personListTemplate  " > 
    {{  for   persons}}
         <tr>
            <td>{{:FirstName}}</td>
            <td>{{:LastName}}</td>
            <td>
                <a href= "  /Person/Edit/{{:PersonID}}  " >Edit</a> | 
                <a href= "  /Person/Details/{{:PersonID}}  " >Details</a> | 
                <a href= "  /Person/Delete/{{:PersonID}}  " >Delete</a>
            </td>
        </tr> 
    {{ / for  }}
 </script>
 //  分页模板 
<script type= "  text/x-jsrender  "  id= "  pagerTemplate  " > 
    {{  if   HasPreviousPage}}
         <a href= "  #  "  onclick= "  getPersonByAjax(1);return false;  " >&lt;&lt;</a>
        <a href= "  #  "  onclick= "  getPersonByAjax({{:PageNumber - 1}});return false;  " >&lt; Prev</a> 
    {{  else  }}
         &lt;&lt;&nbsp;& lt; Prev
    {{ / if  }}
     & nbsp;
    {{  if   HasNextPage}}
         <a href= "  #  "  onclick= "  getPersonByAjax({{:PageNumber + 1}});return false;  " >Next &gt;</a>
        <a href= "  #  "  onclick= "  getPersonByAjax({{:PageCount}});return false;  " >&gt;&gt;</a> 
    {{  else  }}
        Next  &gt;&nbsp;&gt;& gt;
    {{ / if  }}
 </script> 

........

 <script type= "  text/javascript  "  src= "  /Scripts/jquery-1.5.1.min.js  " ></script>
<script type= "  text/javascript  "  src= "  /Scripts/jsrender.js  " ></script>
<script type= "  text/javascript  " > 
    $(function () {
        getPersonByAjax(  1  );
    });

      var  getPersonByAjax =  function (pageNumber) {
        $.getJSON(  "  /Person/AjaxJsRenderPage  "  ,
            {   "  page  "  : pageNumber })
            .success(function (data) {
                $(  "  #personList  "  ).empty();
            //  JsRender渲染、渲染结果(字符串)插入容器                
          $("#personList").append($("#personListTemplate").render(data)); $( " #pager " ).html($( " #pagerTemplate " ).render(data.pager)); }) .error(function (textStatus) { alert( " msg: " + textStatus.statusText); }) .complete(function (jqXHQ) { jqXHQ = null ; }); } </script>

    少去了太多的连接字符串代码(codeless),而且可见性很强,非常容易维护。ok,ajax分页就这么完成了。后头我们在慢慢谈下PagedList的分页思想和整理下JsRender相关的知识。  

 

分类:  ASP.NETMVC

标签:  PagedList ,  Ajax ,  JsRender ,  ASP.NET MVC

作者: Leo_wl

    

出处: http://www.cnblogs.com/Leo_wl/

    

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

版权信息

查看更多关于PagedList+Ajax+JsRender的详细内容...

  阅读:40次