10-大事件
資源地址
項(xiàng)目前期的準(zhǔn)備工作
初始化項(xiàng)目結(jié)構(gòu)
- 將 素材 目錄下的 assets 和 home 文件夾,拷貝到 code 目錄下
- assets > css 文件夾 自己編寫(xiě)的css代碼
- assets > fonts 字體圖標(biāo)文件夾
- assets > images 存放圖標(biāo)文件夾
- assets > js 自己js代碼的文件夾
- assets > lib 第三方依賴(lài)的文件夾
- home > dashboard.html 后臺(tái)首頁(yè)的頁(yè)面效果
- 在 code 目錄下新建 login.html 和 index.html 頁(yè)面
使用GitHub管理大事件的項(xiàng)目
1.登錄注冊(cè)
1.登錄和注冊(cè)表單的切換
注冊(cè)單擊事件,切換表單點(diǎn)擊了對(duì)應(yīng)按鈕,讓對(duì)應(yīng)的div進(jìn)行顯示,另外一個(gè)進(jìn)行隱藏
// 1.點(diǎn)擊注冊(cè),顯示注冊(cè)框,隱藏登錄框$("#link_reg").on("click", function () {$(".reg-box").show();$(".login-box").hide();});// 2.點(diǎn)擊登錄,顯示注登錄框,隱藏注冊(cè)$("#link_login").on("click", function () {$(".reg-box").hide();$(".login-box").show();});2.發(fā)起注冊(cè)用戶的Ajax請(qǐng)求
1實(shí)現(xiàn)登錄表單的驗(yàn)證
-
在layui中,默認(rèn)有幫我們驗(yàn)證表單元素的邏輯
-
導(dǎo)入 layui 的 js 文件
-
為需要驗(yàn)證的表單項(xiàng)添加 lay-verify 屬性,同時(shí)指定具體的校驗(yàn)規(guī)則即可。
-
并且可以添加多個(gè)校驗(yàn)規(guī)則,規(guī)則名用|隔開(kāi)
2.發(fā)起注冊(cè)用戶的Ajax請(qǐng)求
查閱接口文檔,關(guān)注以下幾個(gè)重點(diǎn)信息
- 請(qǐng)求URL
- 請(qǐng)求方式
- 參數(shù)名
- 響應(yīng)數(shù)據(jù)
3.發(fā)起登錄的Ajax請(qǐng)求
- 查閱接口文檔,關(guān)注幾個(gè)重點(diǎn)要(請(qǐng)求URL,請(qǐng)求方式,請(qǐng)求參數(shù),響應(yīng)數(shù)據(jù))
- 請(qǐng)求成功之后提示用戶,保存token信息到本地存儲(chǔ),跳轉(zhuǎn)到后臺(tái)主頁(yè)
- jQuery.ajaxPrefilter()函數(shù)用于指定預(yù)先處理Ajax參數(shù)選項(xiàng)的回調(diào)函數(shù)。
- 在所有參數(shù)選項(xiàng)被jQuery.ajax()函數(shù)處理之前,你可以使用該函數(shù)設(shè)置的回調(diào)函數(shù)來(lái)預(yù)先更改任何參數(shù)選項(xiàng)。
4.提交login分支的代碼到GitHub
- 運(yùn)行 git add . 命令
- 運(yùn)行 git commit -m "完成了登錄和注冊(cè)的功能" 命令
- 運(yùn)行 git push -u origin login 命令 (把本地的login分支推送到遠(yuǎn)程的login分支)
- 運(yùn)行 git checkout master 命令(切換到master分支)
- 運(yùn)行 git merge login 命令(把本地的login分支合并到master分支)
- 運(yùn)行 git push 命令(把本地的master分支推送到遠(yuǎn)程master分支)
- 運(yùn)行 git checkout -b index 命令(創(chuàng)建index分支,用于開(kāi)發(fā)后臺(tái)index頁(yè)面)
5.iframe標(biāo)簽
// 1.默認(rèn)選中首頁(yè) layui-this <li class="layui-nav-item layui-this"><a href="/home/dashboard.html" target="fm"> <span class="iconfont icon-home"></span>首頁(yè) </a> </li>// 2.默認(rèn)顯示首頁(yè) <div class="layui-body"><!-- 內(nèi)容主體區(qū)域 --><iframe name="fm" src="/home/dashboard.html" frameborder="0"></iframe> </div>// 3.去掉動(dòng)畫(huà),隱藏滾動(dòng)條 .layui-body {overflow: hidden; }a {transition: none !important; }6.獲取用戶基本信息
- 定義一個(gè) getUserInfo 函數(shù)(用來(lái)獲取用戶信息),當(dāng)頁(yè)面加載完畢之后調(diào)用這個(gè)函數(shù)
- 利用 $.ajax() 進(jìn)行網(wǎng)絡(luò)請(qǐng)求,查閱文檔,獲取關(guān)鍵信息
- 我們請(qǐng)求的時(shí)候就需要設(shè)置請(qǐng)求頭信息,把我們獲取到的 token 傳遞給后臺(tái)
- 數(shù)據(jù)獲取失敗提示用戶
7.渲染用戶頭像和名稱(chēng)
如果請(qǐng)求成功,我們根據(jù)服務(wù)器返回的數(shù)據(jù)來(lái)渲染頁(yè)面
- 定義 renderAvatar 函數(shù),接收服務(wù)器返回的用戶數(shù)據(jù)
- 獲取用戶的名稱(chēng)
- 設(shè)置歡迎的文本,找到關(guān)鍵元素進(jìn)行設(shè)置
- 按需渲染用戶的頭像,如果用戶有頭像,那么就直接設(shè)置圖片頭像,如果沒(méi)有設(shè)置文本頭像
8.統(tǒng)一為有權(quán)限的接口設(shè)置headers請(qǐng)求頭
- 在 baseAPI的 ajaxPrefilter 中添加如下代碼
- 判斷url 里面是否攜帶 /my/
- 如果攜帶,那么我們就設(shè)置 options.headers
9.實(shí)現(xiàn)退出功能
- 給退出按鈕綁定點(diǎn)擊事件,取消a標(biāo)簽的默認(rèn)行為
- 用戶點(diǎn)擊后,彈出提示框(layui中有彈出層的相關(guān)代碼),如果用戶點(diǎn)擊確認(rèn)
- https://www.layui.com/doc/modules/layer.html#layer.confirm
- 移除本地緩存的 token,并且跳轉(zhuǎn)到登錄頁(yè)面
10.控制用戶的訪問(wèn)權(quán)限
在調(diào)用有權(quán)限接口的時(shí)候,指定complete回調(diào)函數(shù):
// 限制用戶的訪問(wèn)權(quán)限(未登錄直接強(qiáng)制跳轉(zhuǎn)到登錄頁(yè)面)// 不論成功還是失敗,最終都會(huì)調(diào)用 complete 回調(diào)函數(shù)options.complete = function (xhr) {if (xhr.responseJSON.status == 1 && xhr.responseJSON.message === "身份認(rèn)證失敗!") {// 強(qiáng)制清空 token 數(shù)據(jù)localStorage.removeItem("token");// 跳轉(zhuǎn)到登錄頁(yè)location.href = "/login.html";}};11.優(yōu)化權(quán)限控制的代碼
將權(quán)限控制的代碼,從每個(gè)請(qǐng)求中,抽離到 ajaxPrefilter 中:
// 通過(guò)ajax的預(yù)處理函數(shù),給請(qǐng)求的url拼接根地址 // 發(fā)送ajax前進(jìn)行配置的一些屬性,url設(shè)置全局改變一處,所有跟隨改變 $.ajaxPrefilter(function (options) {// 拼接跟地址// options ajax發(fā)送請(qǐng)求前配置的參數(shù)options.url = "http://www.liulongbin.top:3007" + options.url;// 給有權(quán)限的接口,設(shè)置請(qǐng)求頭// 判斷當(dāng)前的請(qǐng)求地址 , 是否需要驗(yàn)證(url 地址中是否包含'/my/')if (options.url.indexOf("/my/") !== -1) {options.headers = { Authorization: localStorage.getItem("token") };}// 限制用戶的訪問(wèn)權(quán)限(未登錄直接強(qiáng)制跳轉(zhuǎn)到登錄頁(yè)面)options.complete = function (xhr) {if (xhr.responseJSON.status === 1 && xhr.responseJSON.message === "身份認(rèn)證失敗!") {// 強(qiáng)制清空 token 數(shù)據(jù)localStorage.removeItem("token");// 跳轉(zhuǎn)到登錄頁(yè)location.href = "/login.html";}}; });提交GIT代碼
2.基本資料
隱藏的和只讀的輸入框
// 隱藏的輸入框 <input type="hidden" name="id">// 只讀的不能修改值的輸入框 readonly(只讀) disabled(禁用) <input type="text" name="username" required disabled class="layui-input" readonly />1.獲取用戶的基本信息
// 1.獲取渲染用戶信息initUserinfo();function initUserinfo() {$.ajax({method: "get",url: "/my/userinfo",success: function (res) {console.log(res);if (res.status !== 0) {return layui.layer.msg(res.message, { icon: 5 });}// 快速為表單賦值layui.form.val("formUserInfo", res.data);},});}2.使用form.val方法快速為表單賦值
// 為表單達(dá)快速賦值 layui.form.val() <form class="layui-form" action="" lay-filter="formUserInfo"> </form>// 為表單達(dá)快速賦值 ("表單名稱(chēng)",數(shù)據(jù)) layui.form.val("formUserInfo", res.data);3.發(fā)起請(qǐng)求更新用戶的信息,驗(yàn)證昵稱(chēng)規(guī)則
// 2.驗(yàn)證昵稱(chēng)規(guī)則layui.form.verify({nickname: function (value) {if (value.length > 6) return "昵稱(chēng)的長(zhǎng)度不能超過(guò)六位";},});// ------------------------------------// 2.修改表單的數(shù)據(jù)$(".layui-form").on("submit", function (e) {e.preventDefault();var data = $(this).serialize();// 發(fā)起 ajax 數(shù)據(jù)請(qǐng)求$.ajax({method: "post",url: "/my/userinfo",data: data,success: function (res) {if (res.status != 0) {return layui.layer.msg(res.message, { icon: 5 });}layui.layer.msg(res.message, { icon: 6 });// 修改完表單數(shù)據(jù)自動(dòng)更新歡迎語(yǔ)// 調(diào)用父頁(yè)面index.js 中的全局函數(shù)getUserInfo// user_info.html 和 indexedDB.html 是父子關(guān)系,需要調(diào)用父類(lèi)的方法// 把index.html 中的獲取信息和渲染信息提到全局作用域中// 調(diào)用父頁(yè)面中的方法,重新渲染用戶的頭像和用戶的信息window.parent.getUserInfo();},});});注意:<iframe> 中的子頁(yè)面,如果想要調(diào)用父頁(yè)面中的方法,使用 window.parent 即可。
3.重置密碼
1.為密碼框定義校驗(yàn)規(guī)則
定義如下的三個(gè)校驗(yàn)規(guī)則:
// 驗(yàn)證密碼的格式(6-12)layui.form.verify({pwd: [/^\S{6,12}$/, "密碼必須是6到12位非空字符"],// 新密碼不能和原始密碼一樣samPwd: function (value) {var oldPwd = $("input[name=oldPwd]").val().trim();console.log(oldPwd);if (value === oldPwd) {return "新舊密碼不能一樣";}},// 新密碼和確認(rèn)新密碼一致的規(guī)則rePwd: function (value) {var newPwd = $("input[name=newPwd]").val().trim();if (newPwd !== value) {return "兩次密碼不一致";}},});2.發(fā)起請(qǐng)求實(shí)現(xiàn)重置密碼的功能
// 修改密碼重置$(".layui-form").on("submit", function (e) {e.preventDefault();let data = $(this).serialize();$.ajax({method: "post",url: "/my/updatepwd",data: data,success: function (res) {if (res.status !== 0) {return layui.layer.msg(res.message, { icon: 5 });}layui.layer.msg(res.message, { icon: 6 });// 重置表單,reset只能用于DOM元素[0]$(".layui-form")[0].reset();},});});4.更換頭像
cropper基本用法.pdf
- 通過(guò) accept 屬性,可以指定,允許用戶選擇什么類(lèi)型的文件
- 獲取拿到用戶選擇的文件 e.target.files
- 將文件轉(zhuǎn)化為文件路徑 ( URL.createObjectURL )
- 減少向服務(wù)器發(fā)送請(qǐng)求次數(shù)
1.實(shí)現(xiàn)裁剪區(qū)域圖片的替換
實(shí)現(xiàn)基本裁剪效果:
// 1.1 獲取裁剪區(qū)域的 DOM 元素var $image = $('#image')// 1.2 配置選項(xiàng)const options = {// 縱橫比aspectRatio: 1,// 指定預(yù)覽區(qū)域preview: '.img-preview'}// 1.3 創(chuàng)建裁剪區(qū)域$image.cropper(options)- 單擊上傳按鈕彈出文件選擇框
- 為文件選擇框綁定 change 事件
2.將裁剪后的頭像上傳到服務(wù)器
將裁剪后的圖片,輸出為 base64 格式的字符串
文件轉(zhuǎn)base64的網(wǎng)址
// 為確定按鈕,綁定點(diǎn)擊事件$('#btnUpload').on('click', function() {// 1. 要拿到用戶裁剪之后的頭像var dataURL = $image.cropper('getCroppedCanvas', {// 創(chuàng)建一個(gè) Canvas 畫(huà)布width: 100,height: 100}).toDataURL('image/png') // 將 Canvas 畫(huà)布上的內(nèi)容,轉(zhuǎn)化為 base64 格式的字符串// 2. 調(diào)用接口,把頭像上傳到服務(wù)器$.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()}})})本地代碼推送到 Git Hub
- user 分支推送到 Git Hub 上 git push -u origin user
- user 分支和 master 合并 git merge user
- master 推送到 Git Hub 上 git push
5.文章分類(lèi)
1.獲取并使用模板引擎渲染表格的數(shù)據(jù)(查)
在頁(yè)面底部導(dǎo)入模板引擎:
<script src="/assets/lib/template-web.js"></script>定義模板:
2.點(diǎn)擊按鈕彈出模態(tài)框,添加分類(lèi) (增)
3.點(diǎn)擊按鈕彈出模態(tài)框,編輯分類(lèi) (改)
4.刪除分類(lèi) (刪)
6.發(fā)布文章
1.渲染文章類(lèi)別對(duì)應(yīng)的下拉選擇框結(jié)構(gòu)
2.渲染封面裁剪區(qū)域
參考 富文本和封面.pdf
//! 【2】初始化富文本編輯器initEditor();//! 【3】 初始化圖片裁剪區(qū)(插件)// 1. 初始化圖片裁剪器var $image = $("#image");// 2. 裁剪選項(xiàng)var options = {aspectRatio: 400 / 280,preview: ".img-preview",};// 3. 初始化裁剪區(qū)域$image.cropper(options);3.更換裁剪區(qū)域的圖片
4.定義文章的發(fā)布狀態(tài)
// 全局變量,保存轉(zhuǎn)態(tài)的值var state = "已發(fā)布";$("#btnSave2").on("click", function () {state = "草稿";});5.基于Form表單創(chuàng)建FormData對(duì)象
6.發(fā)起Ajax請(qǐng)求實(shí)現(xiàn)發(fā)布文章的功能
7.將開(kāi)發(fā)完成的項(xiàng)目代碼推送到GitHub
7.文章列表
1.獲取文章數(shù)據(jù),展示到頁(yè)面(查)
封裝一個(gè)函數(shù),獲取文章數(shù)據(jù)
調(diào)用函數(shù)
2.定義過(guò)濾器函數(shù),對(duì)發(fā)布時(shí)間進(jìn)行格式化
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;};// 定義補(bǔ)零的函數(shù)function padZero(n) {return n > 9 ? n : "0" + n;}3.根據(jù)文章的分類(lèi)和轉(zhuǎn)態(tài)篩選數(shù)據(jù)
4.渲染分頁(yè)按鈕
function renderPage(total) {layui.laypage.render({elem: "pageBox", // 存放按鈕的容器,沒(méi)有#count: total, // 數(shù)據(jù)的總量limit: p.pagesize, // 每頁(yè)顯示的條數(shù)curr: p.pagenum, // 當(dāng)前是第幾頁(yè)// 自定義頁(yè)面按鈕的排版layout: ["page", "next", "prev", "count", "limit", "skip"],limits: [2, 4, 6, 8, 10], // 每頁(yè)顯示條數(shù)的選項(xiàng)// 1)當(dāng)?shù)谝淮武秩痉猪?yè)按鈕時(shí),jump回調(diào)函數(shù)就會(huì)被調(diào)用一次// 2)當(dāng)切換分頁(yè)時(shí),jump 回調(diào)函數(shù)就會(huì)被執(zhí)行jump: function (obj, first) {// obj.分頁(yè)的配置對(duì)象,(obj.limit, obj.curr 當(dāng)前點(diǎn)擊的頁(yè)碼)// first(true,undefined)// 判斷一下是否被點(diǎn)擊,避免無(wú)限循環(huán)if (!first) {// 獲取當(dāng)前的最新頁(yè)碼,更改查詢(xún)參數(shù),調(diào)用函數(shù)重新獲取文章數(shù)據(jù)p.pagenum = obj.curr;// 獲取當(dāng)前最新的每頁(yè)的條數(shù),更改查詢(xún)參數(shù),調(diào)用函數(shù)重新獲取文章數(shù)據(jù)p.pagesize = obj.limit;getArticeList();}},});}5.刪除文章(刪)
1.給刪除按鈕綁定click事件(事件委托)
2.獲取文章id
3.詢(xún)問(wèn)
4.調(diào)接口刪除文章
5.重新渲染(判斷當(dāng)前是否在第一頁(yè))
$("tbody").on("click", ".btn-delete", function () {var id = $(this).attr("data-id");// 單擊刪除按鈕時(shí),統(tǒng)計(jì)刪除按鈕的數(shù)量,并保存var len = $(".btn-delete").length;layer.confirm("是否要?jiǎng)h?", { icon: 3, title: "提示" }, function (index) {$.ajax({url: "/my/article/delete/" + id,success: function (res) {if (res.status !== 0) {return layui.layer.msg(res.message, { icon: 5 });}layui.layer.msg(res.message, { icon: 6 });// 判斷一下是否是當(dāng)前頁(yè)最后一條數(shù)據(jù)if (len === 1) {// 大于一頁(yè)的時(shí)候再減p.pagenum > 1 && p.pagenum--;}getArticeList();},});// 關(guān)閉提示框layer.close(index);});});6.單擊編輯按鈕跳到編輯頁(yè)面
// 1.編輯按鈕是動(dòng)態(tài)添加的,用事件委托$("tbody").on("click", ".btn-edit", function () {// 2.存儲(chǔ)文章的id 本地存儲(chǔ)localStorage.setItem("article_id", $(this).attr("article_id"));// 3.跳轉(zhuǎn)到編輯頁(yè)location.href = "/article/art_edit.html";});8.文章編輯
1.頁(yè)面初始化操作(查)
初始化富文本編輯器
初始化裁剪區(qū)域
2.根據(jù)id獲取文章數(shù)據(jù),并渲染到表單中
geteditData();function geteditData() {$.ajax({url: "/my/article/" + id,success: function (res) {console.log(res);if (res.status !== 0) {return layui.layer.msg(res, message, { icon: 5 });}// 拼接服務(wù)器中的圖片地址$image.cropper("destroy") // 銷(xiāo)毀舊的裁剪區(qū)域.attr("src", "http://www.liulongbin.top:3007" + res.data.cover_img) // 重新設(shè)置圖片路徑.cropper(options); // 重新初始化裁剪區(qū)域// 3).給表單賦值(layui中可以一鍵賦值)layui.form.val("form-edit", res.data);},});}3.獲取表單數(shù)據(jù),上傳服務(wù)器
// 點(diǎn)擊選擇封面上傳文件框打開(kāi)$("#btnChooseImage").on("click", function () {$("#coverFile").click();});// 用戶選擇了新文件則更換裁剪區(qū)$("#coverFile").on("change", function () {// 獲取選中的文件列表var fileList = this.files;// 判斷有沒(méi)有選擇文件if (fileList.length <= 0) {return layui.layer.msg("請(qǐng)選擇文件", { icon: 5 });}var file = fileList[0];// 根據(jù)選擇的文件,創(chuàng)建一個(gè)對(duì)應(yīng)的 URL 地址:var newImgURL = URL.createObjectURL(file);$image.cropper("destroy") // 銷(xiāo)毀舊的裁剪區(qū)域.attr("src", newImgURL) // 重新設(shè)置圖片路徑.cropper(options); // 重新初始化裁剪區(qū)域});獲取數(shù)據(jù)
$("#form-edit").on("submit", function (e) {e.preventDefault();// 收集數(shù)據(jù)(FormData對(duì)象)// var fd = new FormData(form表單dom對(duì)象);var fd = new FormData(this);$image.cropper("getCroppedCanvas", {// 創(chuàng)建一個(gè) Canvas 畫(huà)布width: 400,height: 280,}).toBlob(function (blob) {// 將 Canvas 畫(huà)布上的內(nèi)容,轉(zhuǎn)化為文件對(duì)象// 得到文件對(duì)象后,進(jìn)行后續(xù)的操作// 裁剪完畢后,調(diào)用此回調(diào)函數(shù),參數(shù)blob就是裁剪后的二進(jìn)制文件// 裁剪文章圖片,并追加到fd 中fd.append("cover_img", blob);fd.forEach(function (value, item) {console.log(item, value);});ediltlishArticle(fd);});});封裝一個(gè)調(diào)用發(fā)布文章的接口
// 封裝一個(gè)調(diào)用發(fā)布文章的接口function ediltlishArticle(fd) {$.ajax({method: "post",url: "/my/article/edit",data: fd,// 數(shù)據(jù)是FormData對(duì)象需要配置兩個(gè)額外參數(shù)contentType: false,processData: false,success: function (res) {if (res.status !== 0) {return layui.layer.msg(res.message, { icon: 5 });}layui.layer.msg(res.message, { icon: 6 }, function () {// 提示框關(guān)閉后自哦動(dòng)自動(dòng)執(zhí)行此函數(shù)// 跳轉(zhuǎn)到文章列表// 獲取父頁(yè)面index.html中“文章列表”按鈕標(biāo)簽window.parent.document.getElementById("article-list").click();});},});}總結(jié)
- 上一篇: 如何看待鸿蒙操作系统
- 下一篇: 如何查看自己名下有几张手机卡?