大事件项目第三天(一)

简介: 大事件项目第三天

今日目标

  • 能够完成文章类别的编辑功能
  • 能够完成文章类别的删除功能
  • 能够知道文章列表的分页查询参数的作用
  • 能够完成文章列表的筛选功能
  • 能够参照文档使用LayUI提供的自定义分页UI效果
  • 知道laypage内置模块里面 layout属性和limits 属性的作用
  • 能够解决 jump 回调函数中死循环的问题
  • 能够获取 jump 回调中关键数据,页码值和每页条目数
  • 能够实现分页查询功能
  • 能够完成删除文章功能
  • 能够完成新增文章功能


一、文章类别编辑

7cdd7c70ba2e4cb482d80cc5db9a49db.png


1、点击编辑按钮展示修改文章分类的弹出层

为编辑按钮添加 btn-edit 类名如下

html 结构( /article/art_cate.html )

<button type="button" class="layui-btn layui-btn-xs btn-edit">编辑</button>


定义 修改分类 的弹出层

html 结构( /article/art_cate.html )

<!-- 定义修改分类弹出层模板 -->
<script type="text/html" id="dialog-edit">
    <form class="layui-form" id="form-edit">
      <div class="layui-form-item">
        <label class="layui-form-label">分类名称</label>
        <div class="layui-input-block">
          <input type="text" name="name" required  lay-verify="required" placeholder="请输入分类名称" autocomplete="off" class="layui-input">
    </div>
    </div>
      <div class="layui-form-item">
        <label class="layui-form-label">分类别名</label>
        <div class="layui-input-block">
          <input type="text" name="alias" required  lay-verify="required" placeholder="请输入分类别名" autocomplete="off" class="layui-input">
    </div>
    </div>
      <div class="layui-form-item">
        <div class="layui-input-block">
          <button class="layui-btn" lay-submit lay-filter="formDemo">确认修改</button>
    </div>
    </div>
    </form>
</script>


修改 form 表单样式

css 样式( /assets/css/article/art_cate.css )

#form-add,
#form-edit {
    padding-top: 20px;
    padding-right: 30px;
}


通过 事件委派 的形式,为 btn-edit 按钮绑定点击事件

js 代码( /assets/js/article/art_cate.js )

// 通过代理方式,为 btn-edit 按钮绑定点击事件
let indexEdit = null;
$("tbody").on("click", ".btn-edit", function () {
    // 弹出修改文章分类的弹窗
    indexEdit = layer.open({
        type: 1,
        area: ["500px", "250px"],
        title: "修改文章分类",
        content: $("#dialog-edit").html(),
    });
});


2、为修改文章分类的弹出层填充表单数据

点击不同的条目,那么编辑里面的内容应该是对应的,目前问题,在代码层面,是不知道到底点击了哪个按钮,这里我们可以通过给对应 编辑按钮绑定id来实现

为编辑按钮绑定 data-id 自定义属性

html 结构( /article/art_cate.html )

<button type="button" class="layui-btn layui-btn-xs btn-edit" data-id="{{$value.Id}}">编辑</button>


form元素添加 lay-filter=“form-edit” 属性

html 结构( /article/art_cate.html )

<form class="layui-form" id="form-edit" lay-filter="form-edit">


修改数据需要 id 值,需要给修改弹出层模板里增加隐藏域,用于存放 id

html 结构( /article/art_cate.html )

<form class="layui-form" id="form-edit" lay-filter="form-edit">
    <!-- 隐藏域 -->
    <input type="hidden" name="Id">
    <!-- 省略其他代码 -->
</form>


在展示弹出层之后,根据 id 的值发起请求获取文章分类的数据,并填充到表单中

js 代码( /assets/js/article/art_cate.js )

const id = $(this).attr("data-id");
// 发起请求获取对应分类的数据
$.ajax({
    method: "GET",
    url: "/my/article/cates/" + id,
    success: function (res) {
        layui.form.val("form-edit", res.data);
    },
});


3、更新文章分类的数据
  • 通过 事件委派 的方式,给修改按钮绑定点击事件
  • 查阅接口文档,利用 $.ajax() 发送 post 请求
  • 判断服务器返回的 status 是否等于0,如果不等于,利用 layer.msg 提示用户
  • 如果等于0,代表编辑成功,关闭当前弹出层,调用 initArtCateList() 方法获取最新的数据


js 代码( /assets/js/article/art_cate.js )

// 更新文章分类
$("body").on("submit", "#form-edit", function (e) {
    e.preventDefault();
    $.ajax({
        method: "POST",
        url: "/my/article/updatecate",
        data: $(this).serialize(),
        success: (res) => {
            if (res.status !== 0) {
                return layer.msg("更新分类数据失败!");
            }
            layer.msg("更新分类数据成功!");
            layer.close(indexEdit);
            initArtCateList();
        },
    });
});


二、删除文章分类

952162b6bbda4dd491f50aec34ab9697.png


1、删除文章分类

为删除按钮绑定 btn-delete 类名,并添加 data-id 自定义属性

html 结构( /article/art_cate.html )

<button type="button" class="layui-btn layui-btn-danger layui-btn-xs btn-delete" data-id="{{$value.Id}}">
    删除
</button>


通过代理的形式,为删除按钮绑定点击事件

js 代码( /assets/js/article/art_cate.js )

// 删除文章分类
$("tbody").on("click", ".btn-delete", function () {
    const id = $(this).attr("data-id");
    // 提示用户是否删除
    layer.confirm("确定删除吗?", { icon: 3, title: "提示" }, function (index) {
        $.ajax({
            method: "GET",
            url: "/my/article/deletecate/" + id,
            success: function (res) {
                if (res.status !== 0) {
                    return layer.msg("删除分类失败!");
                }
                layer.msg("删除分类成功!");
                layer.close(index);
                initArtCateList();
            },
        });
    });
});


三、文章列表功能

1、创建文章列表页面

新建 /article/art_list.html 页面

利用 卡片区域搭建结构

html 结构( /article/art_list.html )

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <meta http-equiv="X-UA-Compatible" content="IE=edge" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>Document</title>
        <link rel="stylesheet" href="/assets/lib/layui/css/layui.css" />
        <link rel="stylesheet" href="/assets/css/article/art_list.css" />
    </head>
    <body>
        <!-- 卡片区域 -->
        <div class="layui-card">
            <div class="layui-card-header">文章列表</div>
            <div class="layui-card-body">
                <!-- 筛选区域 -->
                <!-- 列表区域 -->
                <!-- 分页区域 -->
            </div>
        </div>
    </body>
    <script src="/assets/lib/layui/layui.all.js"></script>
    <script src="/assets/lib/jquery.js"></script>
    <script src="/assets/js/baseAPI.js"></script>
    <script src="/assets/lib/template-web.js"></script>
    <script src="/assets/js/article/art_list.js"></script>
</html>


修改 css 样式

css 样式( /assets/css/article/art_cate.css )

html,
body {
    margin: 0;
    padding: 0;
}
body {
    padding: 15px;
    background-color: #f2f3f5;
}

新建 /assets/js/article/art_list.js 脚本文件


2、定义查询参数对象 q

查阅接口文档我们发现,需要提交的参数是比较多的,所以我们可以先来定义一下这个查询的参数对象,由于服务器文章的数量会很多,不能一次性请求回来,这种功能也是很常见的,分页查询

ffa5d7291f1a463680dd01c2a7258c3a.png


  • pagenum 告知服务器我们需要的是第几页数据
  • pagesize 每页能够显示的条目数
  • cate_id 你需要找哪一个分类下的文章,默认是所有文章
  • state 你需要查找的是什么状态的文章


js 代码( /assets/js/article/art_list.js )

// 定义一个查询的参数对象,将来请求数据的时候,
// 需要将请求参数对象提交到服务器
const q = {
    pagenum: 1, // 页码值,默认请求第一页的数据
    pagesize: 2, // 每页显示几条数据,默认每页显示2条
    cate_id: "", // 文章分类的 Id
    state: "", // 文章的发布状态
};


3、请求文章列表数据并使用模板引擎渲染列表结构

定义获取文章列表数据的方法 initTable()

js 代码( /assets/js/article/art_list.js )

$(function() {
    // 获取文章列表数据
    const initTable = () => {
        $.ajax({
            type: "GET",
            url: "/my/article/list",
            data: q,
            success: (res) => {
                if (res.status !== 0) {
                    return layer.msg("获取文章列表失败!");
                }
                // 使用模板引擎渲染页面的数据
                var htmlStr = template("tpl-table", res);
                $("tbody").html(htmlStr);
            },
        });
    };
    initTable();
})


在页面中添加表格结构

html 结构( /article/art_list.html )

<!-- 列表区域 -->
<table class="layui-table">
    <colgroup>
        <col />
        <col width="150" />
        <col width="180" />
        <col width="150" />
        <col width="150" />
    </colgroup>
    <thead>
        <tr>
            <th>文章标题</th>
            <th>分类</th>
            <th>发表时间</th>
            <th>状态</th>
            <th>操作</th>
        </tr>
    </thead>
    <tbody></tbody>
</table>


定义列表数据的模板结构

html 结构( /article/art_list.html )

<!-- 定义 template 模板 -->
<script type="text/html" id="tpl-table">
    {{each data}}
    <tr>
      <td>{{$value.title}}</td>
      <td>{{$value.cate_name}}</td>
      <td>{{$value.pub_date}}</td>
      <td>{{$value.state}}</td>
      <td>
        <button type="button" class="layui-btn layui-btn-xs">编辑</button>
        <button type="button" class="layui-btn layui-btn-danger layui-btn-xs">删除</button>
    </td>
    </tr>
    {{/each}}
</script>


4、定义美化时间格式的过滤器

通过 template.defaults.imports 定义过滤器

js 代码( /assets/js/article/art_list.js )

// 定义美化时间的过滤器
template.defaults.imports.dataFormat = function(date) {
    const dt = new Date(date)
    var y = dt.getFullYear()
    var m = padZero(dt.getMonth() + 1)
    var d = padZero(dt.getDate())
    var hh = padZero(dt.getHours())
    var mm = padZero(dt.getMinutes())
    var ss = padZero(dt.getSeconds())
    return y + '-' + m + '-' + d + ' ' + hh + ':' + mm + ':' + ss
}
// 定义补零的函数
function padZero(n) {
    return n > 9 ? n : '0' + n
}


在模板引擎中使用过滤器

html 结构( /article/art_list.html )

<td>{{$value.pub_date|dataFormat}}</td>


5、绘制筛选区域的UI结构

绘制 UI 结构

  • 默认的 两个select 和 button 都是独自占据一行的
  • 我们可以给三个模块设置 layui-inline
  • 分类的数据是动态进行获取的,第一个下拉框我们先不设置内容
  • 第二个下拉选择框里面内容是死的,我们可以定义三个 option 添加对应的内容即可


html 结构( /article/art_list.html )

<!-- 筛选区域 -->
<form class="layui-form" id="form-search">
    <div class="layui-form-item layui-inline">
        <select name="cate_id"></select>
    </div>
    <div class="layui-form-item layui-inline">
        <select name="state">
            <option value="">所有状态</option>
            <option value="已发布">已发布</option>
            <option value="草稿">草稿</option>
        </select>
    </div>
    <div class="layui-form-item layui-inline">
        <button class="layui-btn" lay-submit lay-filter="formDemo">筛选</button>
    </div>
</form>


6、发起请求获取并渲染文章分类的下拉选择框

定义 initCate 函数请求文章分类的列表数据

  • 利用$.ajax() 发送get请求
  • 判断服务器返回的 status 是否等于0,如果不等于,提示用户
  • 如果等于,通过template得到渲染完毕后的html结构
  • 利用属性选择器渲染到第一个select里面


js 代码( /assets/js/article/art_list.js )

const form = layui.form;
// 初始化文章分类的方法
const initCate = () => {
    $.ajax({
        method: "GET",
        url: "/my/article/cates",
        success: function (res) {
            console.log(res);
            if (res.status !== 0) {
                return layer.msg("获取分类数据失败!");
            }
            // 调用模板引擎渲染分类的可选项
            var htmlStr = template("tpl-cate", res);
            $("[name=cate_id]").html(htmlStr);
            // 通过 layui 重新渲染表单区域的UI结构
            form.render();
        },
    });
};
initCate();


定义分类可选项的模板结构

html 结构( /article/art_list.html )

<script type="text/html" id="tpl-cate">
  <option value="">所有分类</option>
  {{each data}}
  <option value="{{$value.Id}}">{{$value.name}}</option>
  {{/each}}
</script>


7、实现筛选的功能
  • 需要先绑定表单的 submit 事件
  • 在事件里面获取到表单中选中的值
  • 然后把这个值同步到我们 参数对象 q 里面
  • 再次调用 initTable() 方法即可


js 代码( /assets/js/article/art_list.js )

$('#form-search').on('submit', function(e) {
    e.preventDefault()
    // 获取表单中选中项的值
    var cate_id = $('[name=cate_id]').val()
    var state = $('[name=state]').val()
    // 为查询参数对象 q 中对应的属性赋值
    q.cate_id = cate_id
    q.state = state
    // 根据最新的筛选条件,重新渲染表格的数据
    initTable()
})


四、分页功能

4c98017f539245e19be4f86be71c5c0a.png


1、 定义渲染分页的 renderPage 方法

定义渲染分页的方法,接收一个总数量的参数

js 代码( /assets/js/article/art_list.js )

// 定义渲染分页方法
function renderPage(total) {
  console.log(total);
}


在渲染表格完后调用这个方法

js 代码( /assets/js/article/art_list.js )

function initTable() {
    $.ajax({
        method: 'GET',
        url: '/my/article/list',
        data: q,
        success: function(res) {
            if (res.status !== 0) {
                return layer.msg('获取文章列表失败!')
            }
            // 使用模板引擎渲染页面的数据
            var htmlStr = template('tpl-table', res)
            $('tbody').html(htmlStr)
            // 调用渲染分页的方法
            renderPage(res.total)
        }
    })
}


2、调用 laypage.render 方法渲染分页的基本结构

借助layui提供的分页的方式

1f09cf2961ec48ba9e05a67856dca2ae.png


在页面中定义分页的区域

html 结构( /article/art_list.html )

<!-- 分页区域 -->
<div id="pageBox"></div>



调用 laypage.render() 方法来渲染分页的结构

  • elem 分页容器的 id
  • count 总数据条数
  • limit 每页显示几条数据
  • curr 设置默认被选中的分页

js 代码( /assets/js/article/art_list.js

// 定义渲染分页的方法
function renderPage(total) {
    // 调用 laypage.render() 方法来渲染分页的结构
    laypage.render({
        elem: 'pageBox', // 分页容器的 Id
        count: total, // 总数据条数
        limit: q.pagesize, // 每页显示几条数据
        curr: q.pagenum // 设置默认被选中的分页
    })
}


3、在jump回调函数中通过obj.curr获取到最新的页码值
  • 分页发生切换的时候,触发 jump 回调
  • 把最新的页码值赋值给请求参数 q


js 代码( /assets/js/article/art_list.js )

// 定义渲染分页的方法
function renderPage(total) {
    // 调用 laypage.render() 方法来渲染分页的结构
    laypage.render({
        elem: 'pageBox', // 分页容器的 Id
        count: total, // 总数据条数
        limit: q.pagesize, // 每页显示几条数据
        curr: q.pagenum, // 设置默认被选中的分页
        // 分页发生切换的时候,触发 jump 回调
        jump: function(obj) {
            console.log(obj.curr)
            // 把最新的页码值,赋值到 q 这个查询参数对象中
            q.pagenum = obj.curr
        }
    })
}


4、 解决 jump 回调函数发生死循环的问题
  • 目前有个问题,默认这个 jump 是一个循环不断在触发,所以我们还不能直接进行网络请求
  • 触发jump的原因
  • 点击页码的时候会触发 jump 的回调
  • 只要调用了laypage.render()方法就会触发jump回调
  • 我们在定义分页结构的时候,我们调用了 laypage.render() 方法
  • ,一旦调用,我们触发了 jump回调
  • 我们在 jump回调里面又调用了 initTable() 方法
  • initTable() 里面请求成功之后,又调用了 laypage.render() 方法,所以发生了死循环
  • 判断 jump 回调的触发方式就可以解决了
  • jump 的第二个参数就能帮我们判断出来,如果第二个参数为true,就代表是利用 laypage.render() 方法触发的


js 代码( /assets/js/article/art_list.js )

// 定义渲染分页的方法
function renderPage(total) {
    // 调用 laypage.render() 方法来渲染分页的结构
    laypage.render({
        elem: 'pageBox', // 分页容器的 Id
        count: total, // 总数据条数
        limit: q.pagesize, // 每页显示几条数据
        curr: q.pagenum, // 设置默认被选中的分页
        // 分页发生切换的时候,触发 jump 回调
        // 触发 jump 回调的方式有两种:
        // 1. 点击页码的时候,会触发 jump 回调
        // 2. 只要调用了 laypage.render() 方法,就会触发 jump 回调
        jump: function(obj, first) {
            // 可以通过 first 的值,来判断是通过哪种方式,触发的 jump 回调
            // 如果 first 的值为 true,证明是方式2触发的
            // 否则就是方式1触发的
            console.log(first)
            console.log(obj.curr)
            // 把最新的页码值,赋值到 q 这个查询参数对象中
            q.pagenum = obj.curr
            // 根据最新的 q 获取对应的数据列表,并渲染表格
            // initTable()
            if (!first) {
                initTable()
            }
        }
    })
}


5、自定义分页的功能项

查阅了 layui内置模块分页区域的文档后,我们发现可以通过一个参数来配置layout

f18ee07e9ded4162909aa87cfd0be405.png


  • 里面传递的是一个数组,分页的顺序是通过我们配置数组的顺序来显示的
  • 通过limits参数可以来设置每页来显示多少条

js 代码( /assets/js/article/art_list.js )

// 定义渲染分页的方法
function renderPage(total) {
    // 调用 laypage.render() 方法来渲染分页的结构
    laypage.render({
        elem: 'pageBox', // 分页容器的 Id
        count: total, // 总数据条数
        limit: q.pagesize, // 每页显示几条数据
        curr: q.pagenum, // 设置默认被选中的分页
        layout: ['count', 'limit', 'prev', 'page', 'next', 'skip'],
        limits: [2, 3, 5, 10],// 每页展示多少条
        ...
    })
  }


6、实现切换每页展示多少条数据的功能
  • 通过 jump 回调来实现,当我们切换了 每页显示条目数后,会触发这个回调
  • 通过 obj.limit 就能获取用户选择的是第几条
  • 拿到最新条目数后,我们设置给请求对象q里面
  • 然后重新调用 initTable() 来获取最新数据


js 代码( /assets/js/article/art_list.js )

// 定义渲染分页的方法
function renderPage(total) {
    // 调用 laypage.render() 方法来渲染分页的结构
    laypage.render({
        elem: 'pageBox', // 分页容器的 Id
        count: total, // 总数据条数
        limit: q.pagesize, // 每页显示几条数据
        curr: q.pagenum, // 设置默认被选中的分页
        layout: ['count', 'limit', 'prev', 'page', 'next', 'skip'],
        limits: [2, 3, 5, 10],
        // 分页发生切换的时候,触发 jump 回调
        // 触发 jump 回调的方式有两种:
        // 1. 点击页码的时候,会触发 jump 回调
        // 2. 只要调用了 laypage.render() 方法,就会触发 jump 回调
        jump: function(obj, first) {
            // 可以通过 first 的值,来判断是通过哪种方式,触发的 jump 回调
            // 把最新的页码值,赋值到 q 这个查询参数对象中
            q.pagenum = obj.curr
            // 把最新的条目数,赋值到 q 这个查询参数对象的 pagesize 属性中
            q.pagesize = obj.limit
            // 根据最新的 q 获取对应的数据列表,并渲染表格
            if (!first) {
                initTable()
            }
        }
    })
}









目录
相关文章
|
15天前
|
存储 SQL 前端开发
🚀经常发文章的你是否想过定时发布是咋实现的?🚀
🚀经常发文章的你是否想过定时发布是咋实现的?🚀
|
5月前
|
算法 网络协议 Java
双非本科跨专业5面京东,8600小时后收到通知,流下喜悦泪水
自身情况: 1、本科双非,硕士211,均不是计算机相关专业。 2、研究生期间从事的科研项目,材料方向,没有java或者其它编程相关的项目。 3、本科参加比赛较多,电子设计大赛,大学生数学竞赛等,没有程序相关的比赛经历。 4、由于身边的人大多数从事程序员行业,自己其实也很纠结,于是疫情期间(2020年4月份)开始零基础看Java,由于个人原因,5、6月份也没怎么学习,断断续续刷了点题(真后悔5、6月份没好好刷题)。还狠狠地梳理了一遍知识体系
|
前端开发 JavaScript API
大事件项目超详细讲解(可跟做练手项目)(一)
大事件项目超详细讲解(可跟做练手项目)
745 0
大事件项目超详细讲解(可跟做练手项目)(一)
|
12月前
新增闯关模式,邀请好朋友测试
计划为精致1010新增闯关模式,先把游戏原型做出来了,希望朋友们可以先行体验,并给予反馈和意见。
67 0
|
JavaScript 前端开发 开发工具
大事件项目第三天(二)
大事件项目第三天(二)
83 0
大事件项目第三天(二)
|
缓存 JavaScript 前端开发
大事件项目第二天(一)
大事件项目第二天
106 0
大事件项目第二天(一)
|
JavaScript 前端开发 开发工具
大事件项目第二天(二)
大事件项目第二天(二)
119 0
大事件项目第二天(二)
|
开发者 微服务
项目第二天内容介绍 | 学习笔记
快速学习 项目第二天内容介绍
44 0
|
前端开发 JavaScript Java
项目第三天内容介绍 | 学习笔记
快速学习 项目第三天内容介绍
49 0
|
JavaScript 前端开发 开发工具
大事件项目超详细讲解(可跟做练手项目)(二)
大事件项目超详细讲解(可跟做练手项目)(二)
180 0
大事件项目超详细讲解(可跟做练手项目)(二)