• Java项目(三)-- SSM开发社交网站(4)--实现图书类别和图书分页查询


    实现图书列表

    首先,在src/main/webapp目录下创建images、resources、upload三个目录,且在resources目录下引入bootstrap、layui、jquery等前端插件
    在这里插入图片描述
    Bootstrap
    Bootstrap是全球最受欢迎的前端组件库,由推特(TWitter)开源。
    Bootstrap用于开发响应式布局、移动设备优先的WEB项目。
    Bootstrap提供完整的HTML、CSS和JS开发工具集。
    Bootstrap中文网

    在src/main/webapp/WEB-INF/ftl目录下创建index.ftl文件,然后可以删除src/main/webapp目录下的index.html文件。

    DOCTYPE html>
    <html lang="en"><head>
        <meta charset="UTF-8">
        <title>书评网title>
        <meta name="viewport" content="width=device-width,initial-scale=1.0, maximum-scale=1.0,user-scalable=no">
        <meta name="referrer" content="no-referrer">
        <link rel="stylesheet" href="./resources/bootstrap/bootstrap.css">
        <link rel="stylesheet" href="./resources/raty/lib/jquery.raty.css">
        <script src="./resources/jquery.3.3.1.min.js">script>
        <script src="./resources/bootstrap/bootstrap.min.js">script>
        <script src="./resources/art-template.js">script>
        <script src="./resources/raty/lib/jquery.raty.js">script>
        <style>
            .highlight {
                color: red !important;
            }
            a:active{
                text-decoration: none!important;
            }
        style>
    
    
        <style>
            .container {
                padding: 0px;
                margin: 0px;
            }
    
            .row {
                padding: 0px;
                margin: 0px;
            }
    
            .col- * {
                padding: 0px;
            }
        style>
        <#--定义模板-->
        <script type="text/html" id="tpl">
            <a href="/book/{{bookId}}" style="color: inherit">
                <div class="row mt-2 book">
                    <div class="col-4 mb-2 pr-2">
                        <img class="img-fluid" src="{{cover}}">
                    </div>
                    <div class="col-8  mb-2 pl-0">
                        <h5 class="text-truncate">{{bookName}}</h5>
    
                        <div class="mb-2 bg-light small  p-2 w-100 text-truncate">{{author}}</div>
    
    
                        <div class="mb-2 w-100">{{subTitle}}</div>
    
                        <p>
                            <span class="stars" data-score="{{evaluationScore}}" title="gorgeous"></span>
                            <span class="mt-2 ml-2">{{evaluationScore}}</span>
                            <span class="mt-2 ml-2">{{evaluationQuantity}}人已评</span>
                        </p>
                    </div>
                </div>
            </a>
    
            <hr>
        script>
    
        <script>
            $.fn.raty.defaults.path ="./resources/raty/lib/images";
            // loadMore()加载更多数据
            // isReset参数设置为true,代表从第一页开始查询,否则按nextPage查询后续页
            function loadMore(isReset){
                if(isReset == true){
                    $("#bookList").html("");
                    $("#nextPage").val(1);
                }
                var nextPage = $("#nextPage").val();
                var categoryId= $("#categoryId").val();
                var order = $("#order").val();
    
                $.ajax({
                    url : "/books" ,
                    data : {p:nextPage,"categoryId":categoryId , "order":order},
                    type : "get" ,
                    dataType : "json" ,
                    success : function(json){
                        console.info(json);
                        var list = json.records;
                        for(var i = 0 ; i < list.length ; i++){
                            var book = json.records[i];
                            // var html = "
  • " + book.bookName + "
  • ";
    // 将数据结合tpl模板,生成html var html = template("tpl" , book); console.info(html); $("#bookList").append(html); } // 显示星型评价组件 $(".stars").raty({readOnly:true}); // 判断是否到最后一页 if(json.current < json.pages){ $("#nextPage").val(parseInt(json.current) + 1); $("#btnMore").show(); $("#divNoMore").hide(); }else{ $("#btnMore").hide(); $("#divNoMore").show(); } } }) } $(function(){ /*$.ajax({ url : "/books" , data : {p:1}, type : "get" , dataType : "json" , success : function(json){ console.info(json); var list = json.records; for(var i = 0 ; i < list.length ; i++){ var book = json.records[i]; // var html = "
  • " + book.bookName + "
  • "; // 将数据结合tpl模板,生成html var html = template("tpl" , book); console.info(html); $("#bookList").append(html); } // 显示星型评价组件 $(".stars").raty({readOnly:true}); } })*/
    loadMore(true); }) // 绑定加载更多按钮单击事件 $(function(){ $("#btnMore").click(function(){ loadMore(); }) $(".category").click(function () { $(".category").removeClass("highlight"); $(".category").addClass("text-black-50"); $(this).addClass("highlight"); var categoryId = $(this).data("category"); $("#categoryId").val(categoryId); loadMore(true); }) $(".order").click(function(){ $(".order").removeClass("highlight"); $(".order").addClass("text-black-50"); $(this).addClass("highlight"); var order = $(this).data("order"); $("#order").val(order); loadMore(true); }) })
    script> head> <body> <div class="container"> <nav class="navbar navbar-light bg-white shadow mr-auto"> <ul class="nav"> <li class="nav-item"> <a href="/" style="color: #aaa;font-weight: bold"> 书评网 a> li> ul> <#if loginMember??> <h6 class="mt-1"> <img style="width: 2rem;margin-top: -5px" class="mr-1" src="./images/user_icon.png">${loginMember.nickname} h6> <#else> <a href="/login.html" class="btn btn-light btn-sm"> <img style="width: 2rem;margin-top: -5px" class="mr-1" src="./images/user_icon.png">登录 a> #if> nav> <div class="row mt-2"> <div class="col-8 mt-2"> <h4>热评好书推荐h4> div> <div class="col-8 mt-2"> <span data-category="-1" style="cursor: pointer" class="highlight font-weight-bold category">全部span> | <#list categoryList as category> <a style="cursor: pointer" data-category="${category.categoryId}" class="text-black-50 font-weight-bold category">${category.categoryName}a> <#if category_has_next>|#if> #list> div> <div class="col-8 mt-2"> <span data-order="quantity" style="cursor: pointer" class="order highlight font-weight-bold mr-3">按热度span> <span data-order="score" style="cursor: pointer" class="order text-black-50 mr-3 font-weight-bold">按评分span> div> div> <div class="d-none"> <input type="hidden" id="nextPage" value="2"> <input type="hidden" id="categoryId" value="-1"> <input type="hidden" id="order" value="quantity"> div> <div id="bookList"> div> <button type="button" id="btnMore" data-next-page="1" class="mb-5 btn btn-outline-primary btn-lg btn-block"> 点击加载更多... button> <div id="divNoMore" class="text-center text-black-50 mb-5" style="display: none;">没有其他数据了div> div> body>html>
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202
    • 203
    • 204
    • 205
    • 206
    • 207
    • 208
    • 209
    • 210
    • 211
    • 212
    • 213
    • 214
    • 215
    • 216
    • 217
    • 218
    • 219
    • 220
    • 221
    • 222
    显式图书类别

    在com.ql.reader.entity包下创建实体类

    package com.ql.reader.entity;
    
    import com.baomidou.mybatisplus.annotation.IdType;
    import com.baomidou.mybatisplus.annotation.TableId;
    import com.baomidou.mybatisplus.annotation.TableName;
    
    /**
     * 图书分类实体
     */
    @TableName("category")
    public class Category {
        @TableId(type = IdType.AUTO)
        private Long categoryId;
        private String categoryName;
    
        public Long getCategoryId() {
            return categoryId;
        }
    
        public void setCategoryId(Long categoryId) {
            this.categoryId = categoryId;
        }
    
        public String getCategoryName() {
            return categoryName;
        }
    
        public void setCategoryName(String categoryName) {
            this.categoryName = categoryName;
        }
    
        @Override
        public String toString() {
            return "Category{" +
                    "categoryId=" + categoryId +
                    ", categoryName='" + categoryName + '\'' +
                    '}';
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40

    然后在com.ql.reader.mapper包下创建CategoryMapper接口

    package com.ql.reader.mapper;
    
    import com.baomidou.mybatisplus.core.mapper.BaseMapper;
    import com.ql.reader.entity.Category;
    
    /**
     * 图书分类Mapper接口
     */
    public interface CategoryMapper extends BaseMapper<Category> {
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    在src/main/resources/mappers目录下创建category.xml

    
    DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <mapper namespace="com.ql.reader.mapper.CategoryMapper">
    
    mapper>
    
    • 1
    • 2
    • 3
    • 4
    • 5

    然后在com.ql.reader.service包下创建接口CategoryService接口,且在com.ql.reader.service.impl包下创建它的实现类

    package com.ql.reader.service;
    
    import com.ql.reader.entity.Category;
    
    import java.util.List;
    
    public interface CategoryService {
        public List<Category> selectAll();
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    package com.ql.reader.service.impl;
    
    import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
    import com.ql.reader.entity.Category;
    import com.ql.reader.mapper.CategoryMapper;
    import com.ql.reader.service.CategoryService;
    import org.springframework.stereotype.Service;
    import org.springframework.transaction.annotation.Propagation;
    import org.springframework.transaction.annotation.Transactional;
    
    import javax.annotation.Resource;
    import java.util.List;
    @Service("categoryService")
    @Transactional(propagation = Propagation.NOT_SUPPORTED,readOnly = true)
    public class CategoryServiceImpl implements CategoryService {
        @Resource
        private CategoryMapper categoryMapper;
    
        /**
         * 查询所有图书分类
         * @return 图书分类List
         */
        public List<Category> selectAll() {
            List<Category> list = categoryMapper.selectList(new QueryWrapper<Category>());
            return list;
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    然后在src/test/java/com/ql/reader/service/impl目录下编写测试用例,并运行

    package com.ql.reader.service.impl;
    
    import com.ql.reader.entity.Category;
    import com.ql.reader.service.CategoryService;
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.test.context.ContextConfiguration;
    import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
    
    import javax.annotation.Resource;
    
    import java.util.List;
    
    import static org.junit.Assert.*;
    
    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(locations = {"classpath:applicationContext.xml"})
    public class CategoryServiceImplTest {
        @Resource
        private CategoryService categoryService;
    
        @Test
        public void selectAll() {
            List<Category> list = categoryService.selectAll();
            System.out.println(list);
    
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    在这里插入图片描述
    测试没问题,在com.ql.reader.controller包下创建BookController.java

    package com.ql.reader.controller;
    
    import com.ql.reader.entity.Category;
    import com.ql.reader.service.CategoryService;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.servlet.ModelAndView;
    
    import javax.annotation.Resource;
    import java.util.List;
    
    @Controller
    public class BookController {
        @Resource
        private CategoryService categoryService;
    
        /**
         * 显式首页
         * @return
         */
        @GetMapping("/")
        public ModelAndView showIndex(){
            ModelAndView mav = new ModelAndView("/index");
            List<Category> list = categoryService.selectAll();
            mav.addObject("categoryList", list);
            return mav;
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    然后运行项目,在浏览器中访问http://localhost:8080/分类信息显式成功。
    在这里插入图片描述

    实现图书分页查询

    在com.ql.reader.entity包下创建实体类

    package com.ql.reader.entity;
    
    import com.baomidou.mybatisplus.annotation.IdType;
    import com.baomidou.mybatisplus.annotation.TableId;
    import com.baomidou.mybatisplus.annotation.TableName;
    
    @TableName("book")
    public class Book {
        // 图书编号
        // 映射相应主键,并设置为自增
        @TableId(type = IdType.AUTO)
        private Long bookId;
        // 书名
        private String bookName;
        // 子标题
        private String subTitle;
        // 作者
        private String author;
        // 封面图片URL
        private String cover;
        // 图书详情
        private String description;
        // 分类编号
        private Long categoryId;
        // 图书评分
        private float evaluationScore;
        // 评价数量
        private Integer evaluationQuantity;
    
        public Long getBookId() {
            return bookId;
        }
    
        public void setBookId(Long bookId) {
            this.bookId = bookId;
        }
    
        public String getBookName() {
            return bookName;
        }
    
        public void setBookName(String bookName) {
            this.bookName = bookName;
        }
    
        public String getSubTitle() {
            return subTitle;
        }
    
        public void setSubTitle(String subTitle) {
            this.subTitle = subTitle;
        }
    
        public String getAuthor() {
            return author;
        }
    
        public void setAuthor(String author) {
            this.author = author;
        }
    
        public String getCover() {
            return cover;
        }
    
        public void setCover(String cover) {
            this.cover = cover;
        }
    
        public String getDescription() {
            return description;
        }
    
        public void setDescription(String description) {
            this.description = description;
        }
    
        public Long getCategoryId() {
            return categoryId;
        }
    
        public void setCategoryId(Long categoryId) {
            this.categoryId = categoryId;
        }
    
        public float getEvaluationScore() {
            return evaluationScore;
        }
    
        public void setEvaluationScore(float evaluationScore) {
            this.evaluationScore = evaluationScore;
        }
    
        public Integer getEvaluationQuantity() {
            return evaluationQuantity;
        }
    
        public void setEvaluationQuantity(Integer evaluationQuantity) {
            this.evaluationQuantity = evaluationQuantity;
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102

    然后在com.ql.reader.mapper包下创建BookMapper 接口

    package com.ql.reader.mapper;
    
    import com.baomidou.mybatisplus.core.mapper.BaseMapper;
    import com.ql.reader.entity.Book;
    
    public interface BookMapper extends BaseMapper<Book> {
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    然后在src/main/resources/mappers目录下创建book.xml文件

    
    DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <mapper namespace="com.ql.reader.mapper.BookMapper">
    
    mapper>
    
    • 1
    • 2
    • 3
    • 4
    • 5

    在com.ql.reader.service包下创建接口BookService,且在com.ql.reader.service.impl创建它的实现类

    package com.ql.reader.service;
    
    import com.baomidou.mybatisplus.core.metadata.IPage;
    import com.ql.reader.entity.Book;
    
    /**
     * 图书服务
     */
    public interface BookService {
        /**
         * 分页查询图书
         * @param page 页号
         * @param rows 每页记录数
         * @return 分页对象
         */
        public IPage<Book> paging(Integer page, Integer rows);
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    package com.ql.reader.service.impl;
    
    import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
    import com.baomidou.mybatisplus.core.metadata.IPage;
    import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
    import com.ql.reader.entity.Book;
    import com.ql.reader.mapper.BookMapper;
    import com.ql.reader.service.BookService;
    import org.springframework.stereotype.Service;
    import org.springframework.transaction.annotation.Propagation;
    import org.springframework.transaction.annotation.Transactional;
    
    import javax.annotation.Resource;
    
    @Service("bookService")
    @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)
    public class BookServiceImpl implements BookService {
        @Resource
        private BookMapper bookMapper;
    
        /**
         * 分页查询图书
         * @param page 页号
         * @param rows 每页记录数
         * @return 分页对象
         */
        public IPage<Book> paging(Integer page, Integer rows) {
            Page<Book> p = new Page<Book>(page, rows);
            QueryWrapper<Book> queryWrapper = new QueryWrapper<Book>();
            IPage<Book> pageObject = bookMapper.selectPage(p, queryWrapper);
            return pageObject;
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34

    然后在src/test/java/com/ql/reader/service/impl目录下编写测试用例,并运行

    package com.ql.reader.service.impl;
    
    import com.baomidou.mybatisplus.core.metadata.IPage;
    import com.ql.reader.entity.Book;
    import com.ql.reader.service.BookService;
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.test.context.ContextConfiguration;
    import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
    
    import javax.annotation.Resource;
    
    import java.util.List;
    
    import static org.junit.Assert.*;
    
    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(locations = {"classpath:applicationContext.xml"})
    public class BookServiceImplTest {
        @Resource
        private BookService bookService;
    
        @Test
        public void paging() {
            IPage<Book> pageObject = bookService.paging(2, 10);
            List<Book> records = pageObject.getRecords();
            for (Book book: records){
                System.out.println(book.getBookId()+":"+book.getBookName());
            }
            System.out.println("总页数:"+pageObject.getPages());
            System.out.println("总记录数"+pageObject.getTotal());
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    在这里插入图片描述
    然后打开com.ql.reader.controller.BookController.java添加分页查询方法

        /**
         * 分页查询图书列表
         * @param p 页号
         * @return 分页对象
         */
        @GetMapping("/books")
        @ResponseBody
        public IPage<Book> selectBook(Integer p){
            if(p==null){
                p=1;
            }
            IPage<Book> pageObject = bookService.paging(p, 10);
            return pageObject;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    实现图书分页前端部分需要用到JS模板引擎及星星评分组件。
    Art-Template 腾讯JS模板引擎
    Art-Template是一款开源的JS模板引擎,其主要用途为高效的基于模板来生成HTML片段。

    具体前端代码为

    <#--引入jquery组件-->
    <script src="./resources/jquery.3.3.1.min.js">script>
    <#--引入JS模板引擎-->
    <script src="./resources/art-template.js">
    script>
    <#--引入星星评分组件-->
    <script src="./resources/raty/lib/jquery.raty.js">script>
    <#--定义模板-->
    <script type="text/html" id="tpl">
        <a href="/book/{{bookId}}" style="color: inherit">
            <div class="row mt-2 book">
                <div class="col-4 mb-2 pr-2">
                    <img class="img-fluid" src="{{cover}}"/>
                </div>
                <div class="col-8  mb-2 pl-0">
                    <h5 class="text-truncate">{{bookName}}</h5>
    
                    <div class="mb-2 bg-light small  p-2 w-100 text-truncate">{{author}}</div>
    
    
                    <div class="mb-2 w-100">{{subTitle}}</div>
    
                    <p>
                        <span class="stars" data-score="{{evaluationScore}}" title="gorgeous"></span>
                        <span class="mt-2 ml-2">{{evaluationScore}}</span>
                        <span class="mt-2 ml-2">{{evaluationQuantity}}人已评</span>
                    </p>
                </div>
            </div>
        </a>
    
        <hr>
    script>
    
    <script>
        $.fn.raty.defaults.path ="./resources/raty/lib/images";
        // loadMore()加载更多数据
        // isReset参数设置为true,代表从第一页开始查询,否则按nextPage查询后续页
        function loadMore(isReset){
            if(isReset == true){
                $("#bookList").html("");
                $("#nextPage").val(1);
            }
            var nextPage = $("#nextPage").val();
            var categoryId= $("#categoryId").val();
            var order = $("#order").val();
    
            $.ajax({
                url : "/books" ,
                data : {p:nextPage,"categoryId":categoryId , "order":order},
                type : "get" ,
                dataType : "json" ,
                success : function(json){
                    console.info(json);
                    var list = json.records;
                    for(var i = 0 ; i < list.length ; i++){
                        var book = json.records[i];
                        // var html = "
  • " + book.bookName + "
  • ";
    // 将数据结合tpl模板,生成html var html = template("tpl" , book); console.info(html); $("#bookList").append(html); } // 显示星型评价组件 $(".stars").raty({readOnly:true}); // 判断是否到最后一页 if(json.current < json.pages){ $("#nextPage").val(parseInt(json.current) + 1); $("#btnMore").show(); $("#divNoMore").hide(); }else{ $("#btnMore").hide(); $("#divNoMore").show(); } } }) } $(function(){ /*$.ajax({ url : "/books" , data : {p:1}, type : "get" , dataType : "json" , success : function(json){ console.info(json); var list = json.records; for(var i = 0 ; i < list.length ; i++){ var book = json.records[i]; // var html = "
  • " + book.bookName + "
  • "; // 将数据结合tpl模板,生成html var html = template("tpl" , book); console.info(html); $("#bookList").append(html); } // 显示星型评价组件 $(".stars").raty({readOnly:true}); } })*/
    loadMore(true); }) $(function(){ // 绑定加载更多按钮单击事件 $("#btnMore").click(function(){ loadMore(); }) })
    script>
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109

    然后运行项目,在浏览器中访问http://localhost:8080/并按F12把浏览器调成手机模式
    在这里插入图片描述
    鼠标滚轮往下滑到页面底部,点击“点击加载更多”按钮
    在这里插入图片描述
    加载5次后查出了所有数据,页底也没有加载按钮了。
    在这里插入图片描述

  • 相关阅读:
    8、【STM32】定时器(TIM)——中断、PWM、输入捕获实验(一文精通定时器)
    根据经纬度查地址
    R语言——条形图数据可视化的多种方式
    常用网络请求框架Retrofit学习笔记
    World Tour Finals 2019 D - Distinct Boxes 题解
    数据结构——跳表
    TensorFlow 2.9的零零碎碎(六)-模型训练和评价
    nodejs+vue云旅青城系统-旅游网站
    范围求和 II
    LeetCode刷题记录-简单模块(三)
  • 原文地址:https://blog.csdn.net/qq_32091929/article/details/127308558