四、更换头像
1、初步渲染更换头像页面的结构
- 创建
/user/user_avatar.html
页面 - 放入卡片区域 (页面元素 > 面板 > 卡片),修改对应文字信息
- 在侧边栏对应的
a
标签设置href
属性 和target
属性
html 结构( /user/user_avatar.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/user/user_avatar.css" /> </head> <body> <div class="layui-card"> <div class="layui-card-header">更换头像</div> <div class="layui-card-body"> 卡片式面板面板通常用于非白色背景色的主体内<br /> 从而映衬出边框投影 </div> </div> </body> </html>
css 样式( /assets/css/user/user_avatar.css )
html, body { margin: 0; padding: 0; } body { padding: 15px; background-color: #f2f3f5; }
修改 index.html
中对应链接的属性
<a href="/user/user_avatar.html" target="fm"><i class="layui-icon layui-icon-app"></i>更换头像</
2、实现裁剪区域图片的替换
- 在
<head>
中导入cropper.css
样式表:
<link rel="stylesheet" href="/assets/lib/cropper/cropper.css" />
- 在
<body>
的结束标签之前,按顺序导入如下的js
脚本
<script src="/assets/lib/jquery.js"></script> <script src="/assets/lib/cropper/Cropper.js"></script> <script src="/assets/lib/cropper/jquery-cropper.js"></script>
- 在卡片的
layui-card-bod
y 主体区域中,定义如下的HTML
结构
html 结构( /user/user_avatar.html )
<!-- 第一行的图片裁剪和预览区域 --> <div class="row1"> <!-- 图片裁剪区域 --> <div class="cropper-box"> <!-- 这个 img 标签很重要,将来会把它初始化为裁剪区域 --> <img id="image" src="/assets/images/sample.jpg" /> </div> <!-- 图片的预览区域 --> <div class="preview-box"> <div> <!-- 宽高为 100px 的预览区域 --> <div class="img-preview w100"></div> <p class="size">100 x 100</p> </div> <div> <!-- 宽高为 50px 的预览区域 --> <div class="img-preview w50"></div> <p class="size">50 x 50</p> </div> </div> </div> <!-- 第二行的按钮区域 --> <div class="row2"> <button type="button" class="layui-btn">上传</button> <button type="button" class="layui-btn layui-btn-danger">确定</button> </div>
- 美化的样式
css 样式( /assets/css/user/user_avatar.css )
/* 设置卡片主体区域的宽度 */ .layui-card-body { width: 500px; } /* 设置按钮行的样式 */ .row2 { display: flex; justify-content: flex-end; margin-top: 20px; } /* 设置裁剪区域的样式 */ .cropper-box { width: 350px; height: 350px; background-color: cyan; overflow: hidden; } /* 设置第一个预览区域的样式 */ .w100 { width: 100px; height: 100px; background-color: gray; } /* 设置第二个预览区域的样式 */ .w50 { width: 50px; height: 50px; background-color: gray; margin-top: 50px; } /* 设置预览区域下方文本的样式 */ .size { font-size: 12px; color: gray; text-align: center; } /* 设置图片行的样式 */ .row1 { display: flex; } /* 设置 preview-box 区域的的样式 */ .preview-box { display: flex; flex-direction: column; flex: 1; align-items: center; } /* 设置 img-preview 区域的样式 */ .img-preview { overflow: hidden; border-radius: 50%; }
- 实现基本裁剪效果
- 获取裁剪区域的 DOM 元素
- 配置选项: 纵横比、指定预览区域
- 创建裁剪区域
js 代码( /assets/js/user/useravatar.js )
// 1.1 获取裁剪区域的 DOM 元素 var $image = $('#image') // 1.2 配置选项 const options = { // 纵横比 aspectRatio: 1, // 指定预览区域 preview: '.img-preview' } // 1.3 创建裁剪区域 $image.cropper(options)
3、点击弹出文件选择框
默认的文件选择框样式比较丑,所以我们定义这个结构,让其隐藏,给文件选择框指定可以上传的文件类型
html 结构( /user/user_avatar.html )
<input type="file" id="file" accept="image/png,image/jpeg" />
隐藏文件上传框
css 样式( /assets/css/user/user_avatar.css )
/* 隐藏文件上传框 */ #file { display: none; }
下面定义一个按钮,文本是 上传,一旦用户点击按钮,我们手动触发 文件选择框的点击事件
js 代码( /assets/js/user/user_avatar.js )
$('#btnChooseImage').on('click', function() { $('#file').click() })
4、 更换裁剪区域的图片
- 给文件选择框绑定 change 事件
- 用户选择了文件就会触发这个事件,通过
e.target.files
获取用户选择文件列表 - 通过索引0拿到用户选择的文件
- 将文件转化为路径
- 利用
$image
重新初始化裁剪区域
先引入 layui 提供的 js 文件
html 结构( /user/user_avatar.html )
<script src="/assets/lib/layui/layui.all.js"></script>
js 代码( /assets/js/user/useravatar.js )
const layer = layui.layer; // 为文件上传框绑定 change 事件 $("#file").change((e) => { const fileList = e.target.files.length; if (fileList === 0) return layer.msg("请选择文件!"); // 1. 拿到用户选择的文件 let file = e.target.files[0]; // 2. 将文件,转化为路径 var imgURL = URL.createObjectURL(file); // 3. 重新初始化裁剪区域 $image .cropper("destroy") // 销毁旧的裁剪区域 .attr("src", imgURL) // 重新设置图片路径 .cropper(options); // 重新初始化裁剪区域 });
5、将裁剪后的头像上传到服务器
- 为确定按钮,绑定点击事件
- 要拿到用户裁剪之后的头像
- 创建一个 Canvas 画布,将 Canvas 画布上的内容,转化为
base64
格式的字符串
引入 basePI.js 文件
html 结构( /user/user_avatar.html )
<script src="/assets/js/baseAPI.js"></script>
js 代码( /assets/js/user/useravatar.js )
// 为确定按钮绑定点击事件 $("#btnUpload").click(() => { // 1、拿到用户裁切之后的头像 // 直接复制代码即可 const dataURL = $image.cropper("getCroppedCanvas", { // 创建一个 Canvas 画布 width: 100, height: 100, }) .toDataURL("image/png"); // 2、发送 ajax 请求,发送到服务器 $.ajax({ method: "POST", url: "/my/update/avatar", data: { avatar: dataURL, }, success: function (res) { if (res.status !== 0) { return layer.msg("更换头像失败!"); } layer.msg("更换头像成功!"); window.parent.getUserInfo(); }, }); });
6、了解base64
格式的图片
base64
格式你会发现是一段字符串,其实base64
格式的图片,就是利用一段字符串来描述这张图片
好处:能够避免一些额外的图片请求
缺点:体积会比原来图片要大 30% 左右
使用场景:不适用大图片,一些小图片比较适合使用
7、设置头部区域的快捷方式
打开 index.html
,修改头部 个人中心
下的三个快捷方式如下:
html 结构( /index.html )
<dl class="layui-nav-child"> <dd><a href="/user/user_info.html" target="fm">基本资料</a></dd> <dd><a href="/user/user_avatar.html" target="fm">更换头像</a></dd> <dd><a href="/user/user_pwd.html" target="fm">重置密码</a></dd> </dl>
8、本地代码推送到 github
git branch
查看一下分支git add .
添加到暂存区git commit -m
进行提交到本地仓库git push -u origin user
推送到远程仓库的user分支git checkout master
切换到主分支git merge user
合并分支git push
推送到远程仓库的主分支
五、文章分类
1、 创建并显示文章分类页面
创建 /article/art_cate.html
页面,并初始化如下的UI
结构
html 结构( /article/art_cate.html )
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <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_cate.css" /> </head> <body> <!-- 卡片区域 --> <div class="layui-card"> <div class="layui-card-header"> <span>文章类别管理</span> </div> <div class="layui-card-body"> <table class="layui-table"> <colgroup> <col /> <col /> <col width="200" /> </colgroup> <thead> <tr> <th>分类名称</th> <th>分类别名</th> <th>操作</th> </tr> </thead> <tbody> <tr> <td>贤心</td> <td>2016-11-29</td> <td>人生就像是一场修行</td> </tr> <tr> <td>许闲心</td> <td>2016-11-28</td> <td>于千万人之中遇见你所遇见的人,于千万年之中,时间的无涯的荒野里…</td> </tr> </tbody> </table> </div> </div> </body> </html>
css 样式( /assets/css/article/art_cate.css )
html, body { margin: 0; padding: 0; } body { padding: 15px; background-color: #f2f3f5; }
2、快速绘制文章类别页面的基本结构
- 在
layui-card-header
里面添加右侧的按钮 - 给
layui-card-header
设置成flex 布局,让里面内容两侧对齐justify-content: space-between
html 结构( /article/art_cate.html )
<div class="layui-card-header"> <span>文章类别管理</span> <button type="button" class="layui-btn layui-btn-normal layui-btn-sm">添加类别</button> </div>
css 样式( /assets/css/article/art_cate.css )
.layui-card-header { display: flex; justify-content: space-between; align-items: center; }
3、获取并使用模板引擎渲染表格的数据
- 利用模板引擎来进行渲染
- 在页面底部导入模板引擎
导入所需要的 js 文件
html 结构( /article/art_cate.html )
<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_cate.js"></script>
设置 template 模板
html 结构( /article/art_cate.html )
<!-- 定义模板 --> <script type="text/html" id="tpl-table"> {{each data}} <tr> <td>{{$value.name}}</td> <td>{{$value.alias}}</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>
发起数据请求
js 代码( /assets/js/article/art_cate.js )
$(function() { // 获取 表格数据 const initArtCateList = () => { $.ajax({ type: "GET", url: "/my/article/cates", success: (res) => { // 调用 template const htmlStr = template("tpl-table", res); $("tbody").empty().html(htmlStr); }, }); }; initArtCateList(); })
4、使用layer.open
实现弹出层效果
为按钮添加 id
属性
html 结构( /article/art_cate.html )
<button type="button" class="layui-btn layui-btn-normal layui-btn-sm" id="btnAddCate">添加类别</button>
在按钮的点击事件中,通过 layer.open()
展示弹出层
js 代码( /assets/js/article/art_cate.js )
const layer = layui.layer; $("#btnAddCate").click(() => { layer.open({ type: 1, area: ["500px", "250px"], title: "添加文章分类", content: "ABC", }); });
5、 在弹出层中渲染form
表单结构
利用模板引擎的思路,在页面中定义如下的 script
标签
html 结构( /article/art_cate.html )
<!-- 定义弹出层模板 --> <script type="text/html" id="dialog-add"> <form class="layui-form" id="form-add"> <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> <button type="reset" class="layui-btn layui-btn-primary">重置</button> </div> </div> </form> </script>
修改 form 表单样式
css 样式( /assets/css/article/art_cate.css )
#form-add { padding-top: 20px; padding-right: 30px; }
通过 content
属性指定内容
js 代码( /assets/js/article/art_cate.js )
layer.open({ type: 1, area: ['500px', '250px'], title: '添加文章分类', content: $('#dialog-add').html() })
6、实现添加文章分类的功能
发起Ajax请求,注意,我们这个按钮不是写死的,是弹框出来的时候动态生成的,所以我们通过事件委派方式给表单绑定 submit
事件
js 代码( /assets/js/article/art_cate.js )
// 通过代理监听 submit 事件 $("body").on("submit", "#form-add", function (e) { e.preventDefault(); $.ajax({ type: "POST", url: "/my/article/addcates", data: $(this).serialize(), success: (res) => { if (res.status !== 0) return layer.msg("新增分类失败!"); initArtCateList(); layer.msg("新增分类成功!"); layer.close(indexAdd); }, }); });
预先保存弹出层的索引,方便进行关闭
js 代码( /assets/js/article/art_cate.js )
let indexAdd = null; $("#btnAddCate").click(() => { indexAdd = layer.open({ type: 1, area: ["500px", "250px"], title: "添加文章分类", content: $("#dialog-add").html(), }); });