個人部落格 Django 評論模組開發總結【四】JavaScript邏輯,請求渲染校驗資料
阿新 • • 發佈:2020-08-25
JavaScript邏輯,請求渲染校驗資料
個人網站開通評論了 https://www.charmcode.cn/article/2020-07-09_Comment
歡迎評論交流
思路分析
首先得理清楚,需要做那些功能
- 確定是否登入(通過cookie 儲存的使用者資訊判斷)
- 使用者輸入內容校驗,以及提示使用者輸入字數,涉及到防抖函式
- 請求評論資料,然後渲染資料列表(目前不考慮做分頁)
- 新增評論資料,新增前先過濾資料,提交按鈕防抖,提交後清空輸入框並且給出介面回撥提示,評論成功或者失敗。
工具類函式
思路分析中用到的幾個點,需要封裝以下工具類函式
- 1 獲取cookie值
/** * 獲取cookie工具函式 * */ function getCookie(c_name) { if (document.cookie.length > 0) { let c_start = document.cookie.indexOf(c_name + "="); if (c_start !== -1) { c_start = c_start + c_name.length + 1; let c_end = document.cookie.indexOf(";", c_start); if (c_end === -1) c_end = document.cookie.length; return unescape(document.cookie.substring(c_start, c_end)); } } return ""; }
- 2 輸入框,提交按鈕, 防抖函式
/**
* 防抖工具函式
* */
function debounce(fun, delay) {
return function (args) {
let that = this;
let _args = args;
clearTimeout(fun.id);
fun.id = setTimeout(function () {
fun.call(that, _args)
}, delay)
}
}
- 3 過濾輸入評論資料的函式(當然後端也有一次過濾)
/** * 過濾輸入資料工具函式 * author:CharmCode.cn * */ function clearValue(v) { v = v.trim(); // 去掉特殊字元 v = v.replace(/[\'\"\\\/\b\f\n\r\t]/g, ''); v = v.replace(/[\#\$\%\^\&\*\{\}\:\"\L\<\>\?]/g, ''); // 多個空格|換行 替換成一個 v = v.replace(/[\s\n]{2,}/g, " "); // 擷取前100個字元 v = v.slice(0, 100); return v }
- 4 封裝的http請求庫
返回一個promise物件:可以參考我上一篇文章
/**
* fetch函式封裝
* @author:CharmCode.cn
* @return: promise object
* */
function requests(path, method = "GET", data = {}, headers = {'content-type': 'application/json'}) {
method = method.toUpperCase();
// 預設請求頭
let requestHeader = {
headers,
method
};
// 如果是get請求
if (method === "GET") {
// 轉換拼接get引數
let esc = encodeURIComponent;
let queryParams = Object.keys(data)
.map(k => `${esc(k)}=${esc(data[k])}`)
.join('&');
if (queryParams) path += `?${queryParams}`;
} else {
// 其他請求 放入body裡面
requestHeader.body = JSON.stringify(data)
}
// 可以在這封裝一個回撥函式,請求攔截
// 傳送請求並返回 promise 物件 注意 fetch不會攔截其他異常請求️
return fetch(`${window.location.origin}${path}`, requestHeader).then(
// 可在這裡封裝 響應攔截函式
response => response.json()
)
}
js邏輯實現
獲取使用者資訊
頁面一載入,js就會獲取使用者資訊,如果獲取到了,就把登入按鈕給去掉,替換成使用者的資訊,然後去掉輸入框的只讀屬性。
function checkLogin() {
let username = getCookie("github_username");
let avatar = getCookie("github_avatar");
if (username && avatar) {
// 獲取到 說明已經登入
let github_info = document.getElementById("github-info");
github_info.innerHTML = `<img class="github-image"
src=${avatar}>
<span class="github-name">${username}</span>`;
// 已經登入 移除輸入框只讀屬性
let input = document.getElementById("veditor");
input.removeAttribute("readonly")
}
}
載入評論
這一步和上面從cookie中獲取使用者資訊,是非同步進行的。
演示了使用fetch傳送請求的便捷性, 當然可以封裝一個響應攔截器,統一攔截狀態碼不為200的響應。
// 獲取評論
function loadCommit() {
let article_url = window.location.pathname.split("/").pop();
requests(
"/article/comment/",
"GET",
{
article_url: article_url
}
).then((data) => {
if (data.code === 200) {
// 獲取到評論框物件
let commit = document.getElementById("show-commit");
// 每次載入評論前先置為空
commit.innerHTML = "";
let strTemp = "";
for (let i of data.data) {
// 處理GitHub頭像載入失敗
let onerrorImg = i.userInfo.avatar.replace(/avatars\d/, 'avatars3');
strTemp += `<div class="comments-item">
<div class="comment-user-head">
<img src="${i.userInfo.avatar}" onerror="imgerrorfun("${onerrorImg}");">
</div>
<div class="comment-content">
<div class="comment-body">
${i.content}
</div>
<div class="comment-time">
<a href="${i.userInfo.github_add}" target="_blank">${i.userInfo.username}</a>
${i.time}
<span id="reply" style="padding: 3px;color: #00a8c6">
回覆
</span>
</div>
</div>
</div>`
}
commit.innerHTML = strTemp;
}
})
}
檢測輸入 防抖
首先我是有檢測,使用者輸入評論的字數的,當然不是實時監控檢測,有5毫秒的延遲檢測。
// 檢測輸入
function inputTextChange() {
let input = document.getElementById("veditor");
// 防抖監聽輸入事件
input.addEventListener("input", debounce(() => {
let inputLen = input.value.length;
let surplus = 100 - inputLen;
let valueTip = document.getElementById("valueLen");
if (surplus >= 1) {
valueTip.innerHTML = `還能輸入 ${surplus} 字`
} else {
valueTip.innerHTML = `已經超過100字,將擷取前100字`
}
}, 500), false)
}
提交評論
提交評論這塊我也做了防抖處理,然後提交前驗證資料,還有就是提交後訊息回撥,提示是否回撥成功。
// 提交評論資料
function commitReply() {
let username = getCookie("github_username");
let avatar = getCookie("github_avatar");
let commit_btn = document.getElementById("commit");
commit_btn.addEventListener("click", debounce(() => {
if (username && avatar) {
// 獲取textarea物件
let inputValue = document.getElementById("veditor");
// 過濾資料
inputValue = clearValue(inputValue.value);
if (inputValue.length >= 2) {
// 傳送post請求
submitCommit(username, inputValue, replayTip);
// 將textarea 值置為空
document.getElementById("veditor").value = "";
// 重新載入評論
loadCommit()
}
} else {
alert("請登入後在輸入")
}
}, 500), false);
}
回撥提示
這是一個提交評論的回撥提示,然後最後面的定時器,設定提示資訊停留時間
// 回撥後的提示資訊
function replayTip(code) {
// replyTipSpan
let tip = document.getElementById("replyTipSpan");
if (code === 200) {
tip.innerHTML = `<span style='color:#67C23A'>評論成功</span>`
} else {
tip.innerHTML = `<span style='color:#F56C6C'>評論失敗</span>`
}
// 清理提示
setTimeout(() => {
tip.innerHTML = ""
}, 8000)
}
頭像載入錯誤處理
由於我使用的是Github第三方登入, github cdn很多,所以我了圖片的onerror="imgerrorfun("${onerrorImg}")
這個載入錯誤處理事件。以免載入不出來頭像等資源時,像Stack Overflow一樣一直卡在哪裡載入
// 圖片載入失敗後處理函式
function imgerrorfun(onerrorImg) {
let img = event.srcElement;
img.src = onerrorImg;
img.onerror = null; // 把傳遞的onerror事件取消,控制不要一直跳動
}
總結
整個評論模組了,還不是特別完善,比如載入更多評論(翻頁),回覆功能,評論注水(惡意刷介面)檢測等都沒有開發。