当我坐在那架破旧古钢琴旁边的时候,我对 最幸福的国王也不羡慕。—— 海顿

Thinkjs学习笔记---thinkjs实现文章日期归档和分页

需求(Demand )

因为博客以前用的wordpress的缘故,所以基本上的路由沿用了wordpress的规则。 在wordpress中文章按日期归档比较灵活:

article/date/年
article/date/年/月
article/date//月/日

article/date//page/页码
article/date//月/page/页码
article/date//月//page/页码

好在thinkjs在路由这块也很灵活,研究了几天,总算给实现了😴

关键点(Key Point)

分页api

thinkjs中专门提供了pageapi来进行分页查询数据

model.page(page, listRows)

  • page {Number} 当前页,从 1 开始
  • listRows {Number} 每页的条数
  • return {this}

自定义路由之正则路由(router)

路由配置src/home/config/route.js

export default [
  [/^article\/date\/(\d+)$/, "home/article/date?year=:1"]
];

上面的正则会匹配类似 article/date/2016 这样的 pathname,识别后新的 pathname 为 home/article/date,也就是对应到了home模块下的article控制器的dateAction,并且将捕获到的值赋值给参数 year ,这样在控制器里就可以通过 this.get 方法 来获取该值。

这里很关键,捕获的值来源于正则里的子分组(\d+),如果有多个则可以通过在路由配置中用 :1,:2,:3 来获取对应的值。

分页查询数据(countSelect)

这个方法与page方法配合,thinkjs会帮我们返回总页数,当前页码,每页显示页数等信息,这些都是后面分页模板编写的基础。

返回值格式如下:

{
  numsPerPage: 10, //每页显示的条数
  currentPage: 1, //当前页
  count: 100, //总条数
  totalPages: 10, //总页数
  data: [{ //当前页下的数据列表
    title: "文章标题",
    author: "文章作者",
    desc:"文章摘要"
  }, ...]
  }

模板(template)

有了数据,在页面要显示出来自然少不了模板 之前选择的是nunjucks模板引擎(很强大的js模板引擎模仿的python的jinja2引擎),所以实现起来也相对轻松,我准备把它提取成公用的模板,命名为pagination.由于每个分页的模块对应路由肯定各不相同,所以还得做点额外工作,这里我把前缀提取了出来,用一个变量来标识.

实践(Practice)

template

<div class="pagination">
    {% if pageData.prevPage%}
        <a class="btn-prev" href="{{pageFor}}page/{{pageData.prevPage}}">上一页</a>
    {% endif %}

    {% for i in range(pageData.pageStart, pageData.pageEnd+1) -%}
      <a href="{{pageFor}}page/{{i}}" class="pagination-item {%if pageData.currentPage==i %}active{%endif%}">{{i}}</a>
    {%- endfor %}

    {% if pageData.nextPage%}
        <a class="btn-next" href="{{pageFor}}page/{{pageData.nextPage}}">下一页</a>
    {% endif %}

    <span class="count">{{pageData.pageCount}}</span>
</div>

controller

    async dateAction() {
        let params = this.get();
        let startDate, endDate,date,query,title,pageFor;
        let currentPage = this.get("page")||1;
        let pagesize = this.get("pagesize")||10;
        // 如果具体到天
        if(params.day) {
          date = new Date(params.year,params.month - 1,params.day);
          startDate = date.getTime();
          endDate = startDate + 3600*24*1000;
          title = "归档:\""+ think.datetime(date,"YYYY年MM月DD日") + "\"";
          pageFor = "/article/date/" + params.year + '/' + (params.month+1) + '/'+ params.day + '/';
        }
        query = {"create_time":{$gte:new Date(startDate),$lte:new Date(endDate)},"status": 1};
        let model = this.model("article");
        let list = await model.where(query).page(currentPage,pagesize).countSelect();
        let pageData = this.pagination(list);
        if(list && list.data.length>0){
            this.assign({
                "list":list,
                "title":title,
                pageData:pageData,
                pageFor:pageFor
            });
            return this.displayView('list');
        } else  {
            this.errorHandler.displayError(404);
        }
    }

    /**
    * @description 处理分页数据
    */
    pagination($list){
        let pageNum = 6; //最大显示的分页按钮数
        let pageStart = 1;
        let pageEnd = 6;
        let pageCount = $list.totalPages;
        let currentPage = $list.currentPage;
        let nextPage = currentPage + 1 <= pageCount ? currentPage + 1:null;
        let prevPage = currentPage - 1 || null;

        if(currentPage<=pageNum/2+1){
            pageStart=1;
            pageEnd=pageNum;
        }else{
            pageStart=currentPage - pageNum / 2;
            pageEnd = currentPage + pageNum / 2 - 1;
        }
        if (pageEnd >pageCount) {
            pageEnd = pageCount;
        }
        if (pageEnd <= pageNum) {
            pageStart= 1;
        }

        return {
            pageCount:pageCount,
            nextPage:nextPage,
            prevPage:prevPage,
            currentPage:currentPage,
            pageStart:pageStart,
            pageEnd:pageEnd
        }
    }

总结(Summary)

起初用的自定义之规则路由:

export default [
  ["group/:year/:month", "home/group/list"]
]

谁知道遇到了蛮多坑的,不分页时还好,年月日三种路由都能正常匹配。不过加上分页后,就悲剧了😫

export default [
  ["article/date/:year/:month/:day", "home/article/date"],
  [/^article\/date\/(\d+)\/page\/(\d+)$/, "home/article/date?year=:1&page=:2&pagesize=10"]
]

上述两个路由就开始互掐了,后面索性全用了正则路由,再次觉得正则真心强大。希望以上写的略显琐碎笔记对需要在thinkjs进行分页的同学有所帮助😁(End).

分享

分享本文章

文章来源
210510

2016-11-26

标签

thinkjs

right left pencil2 css3 node design eye tags search rss back user pacman film