基于JavaScript實現(xiàn)一個動態(tài)脫敏指令
所謂的數(shù)據(jù)脫敏,是指在不影響數(shù)據(jù)分析結(jié)果的準(zhǔn)確性前提下,對原始數(shù)據(jù)中的敏感字段進行處理,從而降低數(shù)據(jù)敏感度和減少個人隱私風(fēng)險的技術(shù)措施。在現(xiàn)在這個大數(shù)據(jù)時代,個人隱私信息在互聯(lián)網(wǎng)上傳播的幾率是很大的,因此作為前端工程師,我們很多時候也需要在視圖層面對數(shù)據(jù)進行脫敏展示處理。
效果展示
體驗地址
http://jyeontu.xyz/jvuewheel/#/JDesensitizationView
指令實現(xiàn)
脫敏函數(shù)
參數(shù)處理
- 接受三個參數(shù) str(待脫敏的字符串)、config(脫敏配置對象)和 fn(可選的自定義處理函數(shù))。首先對 str 進行了 trim 操作并強制轉(zhuǎn)換為字符串類型,確保輸入數(shù)據(jù)的規(guī)范性。
- 若存在自定義函數(shù) fn,則直接調(diào)用該函數(shù)并返回結(jié)果,給予開發(fā)者靈活定制脫敏邏輯的空間。
- 當(dāng) str 為空字符串時,直接返回空,簡潔處理邊界情況。
const desensitization = (str, config, fn) => { str = str.trim() + ""; if (fn) { return fn(str); } if (!str) { return ""; } ………… }
配置解析與默認值設(shè)定
- 從 config 中解構(gòu)出 before(脫敏前保留的字符數(shù))和 after(脫敏后保留的字符數(shù)),并提供了默認值 0。同時獲取 type(數(shù)據(jù)類型標(biāo)識,如 phone、email 等)和 ch(用于替換敏感字符的符號,默認為
*
)。 - 根據(jù)不同的 type,對 before 和 after 進行了智能的默認值調(diào)整。例如對于 phone 類型,若字符串長度小于 11,則合理調(diào)整 before 為 2,after 為 2,以適配常見的手機號碼格式;對于 email 類型,則根據(jù) @ 符號分割字符串來確定 after 的值,精準(zhǔn)定位域名部分進行保護。
let { before = 0, after = 0 } = config; const { type, ch = "*" } = config; const len = str.length; switch (type) { case "phone": before = "3"; after = "4"; if (len < 11) { before = 2; after = 2; } break; case "email": before = "1"; if (str.split("@").length > 1) after = str.split("@")[1].length + 1; break; case "idCard": before = "3"; after = "4"; break; case "name": before = "1"; after = len > 2 ? 1 : 0; break; }
構(gòu)造正則進行脫敏
計算出需要顯示的真實字符數(shù) show,基于此構(gòu)建正則表達式 reg。通過 replace 方法,按照正則表達式的匹配規(guī)則,用指定的 ch 符號替換中間的敏感字符,最終返回脫敏后的字符串。
const show = Math.max(len - before - after, 0); const reg = [ new RegExp(`^(.{${before}}).{${show}}(.{${after}})$`), `$1${ch.repeat(show)}$2`, ]; return str.replace(reg[0], reg[1]);
指令執(zhí)行函數(shù)
參數(shù)提取與初始值獲取
從指令綁定的值 binding.value 中提取出 params,進一步解構(gòu)得到 config 和 fn。同時獲取元素 el 的相關(guān)屬性值,如 innerHTML、getAttribute 獲取的原始值 originVal,并初始化 inputOriginVal,為后續(xù)處理用戶輸入做準(zhǔn)備。
const params = binding.value || {}; const { config, fn } = params; let inputOriginVal = ""; let originVal = el.getAttribute("desensitization-originVal") || "";
文本節(jié)點脫敏處理
當(dāng) el.innerHTML 存在時,意味著是對頁面展示的文本內(nèi)容進行脫敏。首先確保 originVal 的獲取,若為空則從 el.innerText 中獲取并設(shè)置為原始值,存儲在自定義屬性 desensitization-originVal 中,然后調(diào)用 desensitization 函數(shù)對 originVal 進行脫敏處理,并更新 el.innerHTML。
if (el.innerHTML) { if (!originVal) { el.setAttribute("desensitization-originVal", el.innerText); originVal = el.innerText; } el.innerHTML = desensitization(originVal, config, fn); return; }
輸入框交互處理
針對輸入框元素,先移除之前可能存在的焦點和失焦事件監(jiān)聽器,避免重復(fù)綁定。然后分別為 focus 和 blur 事件添加監(jiān)聽器。在 focus 事件中,將輸入框的值恢復(fù)為原始輸入值 inputOriginVal;在 blur 事件中,獲取當(dāng)前輸入值 value,更新 inputOriginVal,并調(diào)用 desensitization 函數(shù)對 value 進行脫敏處理,最后更新輸入框的顯示值。
if (fouceListerner) { el.removeEventListener("focus", fouceListerner); } fouceListerner = el.addEventListener("focus", (event) => { event.target.value = inputOriginVal; }); if (blurListerner) { el.removeEventListener("blur", blurListerner); } blurListerner = el.addEventListener("blur", (event) => { const value = event.target.value; inputOriginVal = value; const newVal = desensitization(value, config, fn); event.target.value = newVal; });
指令生命周期鉤子
bind
當(dāng)指令首次綁定到元素上時執(zhí)行。在此處調(diào)用 doDesensitization 函數(shù),嘗試進行脫敏處理,若出現(xiàn)錯誤則捕獲并打印 bindErr 相關(guān)的錯誤信息,確保指令初始化的穩(wěn)定性。
bind: function (el, binding) { try { doDesensitization(el, binding); } catch (err) { console.error("bindErr", err); } }
update
當(dāng)指令所在組件的數(shù)據(jù)更新時觸發(fā)。首先判斷元素 el 的 innerText 是否存在,若存在則調(diào)用 doDesensitization 函數(shù)進行重新脫敏處理,同樣對錯誤進行捕獲并打印 updateErr,保證數(shù)據(jù)更新后的脫敏效果持續(xù)有效。
update: function (el, binding) { if (!el.innerText) return; try { doDesensitization(el, binding); } catch (err) { console.error("updateErr", err); } }
unbind
當(dāng)指令從元素上移除時執(zhí)行。主要任務(wù)是移除之前綁定的焦點和失焦事件監(jiān)聽器。
unbind: function (el) { if (fouceListerner) { el.removeEventListener("focus", fouceListerner); } if (blurListerner) { el.removeEventListener("blur", blurListerner); } }
指令使用
電話號碼脫敏
內(nèi)置有電話的脫敏類型,對于11位數(shù)的手機號碼,脫敏方式是顯示前3位和后4位;對于小于11位數(shù)的,比如7位數(shù)的電話號碼,脫敏方式是顯示前2位和后2位。
<div class="content"> <input v-JDesensitization:params="params" placeholder="輸入需要脫敏的字符" class="input-content" /> <div v-JDesensitization:params="params" class="div-content"> 15012345678 </div> </div> <script> export default{ data(){ return { params:{ "config": { "type": "phone", "before": , "after": "", "ch": "*" }, "fn": "" }, } } } </script>
身份證號碼脫敏
內(nèi)置有身份證號碼的脫敏類型,脫敏方式是顯示前3位和后4位;
<div class="content"> <input v-JDesensitization:params="params" placeholder="輸入需要脫敏的字符" class="input-content" /> <div v-JDesensitization:params="params" class="div-content"> 330621199909091234 </div> </div> <script> export default{ data(){ return { params:{ "config": { "type": "idCard", "before": , "after": "", "ch": "*" }, "fn": "" }, } } } </script>
姓名脫敏
內(nèi)置有姓名的脫敏類型,兩個字的姓名脫敏方式是顯示第1位;大于兩個字的姓名脫敏方式是顯示第一個字和最后一個字。
<div class="content"> <input v-JDesensitization:params="params" placeholder="輸入需要脫敏的字符" class="input-content" /> <div v-JDesensitization:params="params" class="div-content"> 張三風(fēng) </div> </div> <script> export default{ data(){ return { params:{ "config": { "type": "name", "before": , "after": "", "ch": "*" }, "fn": "" }, } } } </script>
郵箱脫敏
內(nèi)置有郵箱的脫敏類型,脫敏方式是顯示第一位和@
及以后的字符。
<div class="content"> <input v-JDesensitization:params="params" placeholder="輸入需要脫敏的字符" class="input-content" /> <div v-JDesensitization:params="params" class="div-content"> 123456@163.com </div> </div> <script> export default{ data(){ return { params:{ "config": { "type": "email", "before": , "after": "", "ch": "*" }, "fn": "" }, } } } </script>
自定義脫敏
可以自定義脫敏代替字符,默認為*
修改 config 中的 ch 參數(shù)即可自定義脫敏代替字符
params: { config: { type: "phone", before: "", after: "", ch: "~", }, fn: "", }
可以自定義脫敏字符頭尾顯示位數(shù)
修改 config 中的 before 和 after 參數(shù)即可自定義脫敏顯示位數(shù),type 需要修改為內(nèi)置類型以外的,直接傳空即可。
params: { config: { type: "", before: "2", after: "2", ch: "~", }, fn: "", }
可以自定義脫敏函數(shù)進行脫敏
可以直接在參數(shù)的 fn 中傳入一個脫敏函數(shù),如果傳入了 fn,其優(yōu)先級最高,則其他參數(shù)都不會生效,會直接調(diào)用傳入的 fn函數(shù) 進行脫敏,如:
(str) => { return str[0] + '@'.repeat(str.length - 1); }
應(yīng)用場景
用戶信息填寫,輸入框聚焦時顯示真實數(shù)據(jù)供用戶進行修改,失焦時顯示脫敏后的數(shù)據(jù)。
(至于為什么會有這個場景,需要去問一下產(chǎn)品經(jīng)理)
到此這篇關(guān)于基于JavaScript實現(xiàn)一個動態(tài)脫敏指令的文章就介紹到這了,更多相關(guān)JavaScript動態(tài)脫敏指令內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
JavaScript實現(xiàn)多態(tài)和繼承的封裝操作示例
這篇文章主要介紹了JavaScript實現(xiàn)多態(tài)和繼承的封裝操作,結(jié)合實例形式分析了javascript中多態(tài)與繼承的實現(xiàn)及封裝相關(guān)操作技巧,需要的朋友可以參考下2018-08-08詳解webpack import()動態(tài)加載模塊踩坑
這篇文章主要介紹了詳解webpack import()動態(tài)加載模塊踩坑,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-07-07Webpack常見靜態(tài)資源處理-模塊加載器(Loaders)+ExtractTextPlugin插件
這篇文章主要介紹了Webpack常見靜態(tài)資源處理-模塊加載器(Loaders)+ExtractTextPlugin插件,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-06-06js關(guān)閉模態(tài)窗口刷新父頁面或跳轉(zhuǎn)頁面
點擊按鈕時,彈出B窗口(模態(tài))。在B窗口中添加數(shù)據(jù),提交后,要求B窗口自關(guān)閉,然后刷新A窗口(父),需要的朋友可以了解下2012-12-12如何基于webpack創(chuàng)建plugin并發(fā)布npm包
webpack 插件是一個具有 apply 方法的 JavaScript 對象,apply 方法會被 webpack compiler 調(diào)用,并且在 整個編譯生命周期都可以訪問 compiler 對象,這篇文章主要介紹了基于webpack創(chuàng)建plugin并發(fā)布npm包,需要的朋友可以參考下2024-07-07深入webpack打包原理及l(fā)oader和plugin的實現(xiàn)
這篇文章主要介紹了深入webpack打包原理及l(fā)oader和plugin的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-05-05完美解決input[type=number]無法顯示非數(shù)字字符的問題
下面小編就為大家?guī)硪黄昝澜鉀Qinput[type=number]無法顯示非數(shù)字字符的問題。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-02-02