说在前面
🎈所谓的数据脱敏,是指在不影响数据分析结果的准确性前提下,对原始数据中的敏感字段进行处理,从而降低数据敏感度和减少个人隐私风险的技术措施。在现在这个大数据时代,个人隐私信息在互联网上传播的几率是很大的,因此作为前端工程师,我们很多时候也需要在视图层面对数据进行脱敏展示处理。
效果展示
体验地址
指令实现
脱敏函数
参数处理
- 接受三个参数 str (待脱敏的字符串)、config (脱敏配置对象)和 fn (可选的自定义处理函数)。首先对 str 进行了 trim 操作并强制转换为字符串类型,确保输入数据的规范性。
- 若存在自定义函数 fn,则直接调用该函数并返回结果,给予开发者灵活定制脱敏逻辑的空间。
- 当 str 为空字符串时,直接返回空,简洁处理边界情况。
javascript
const desensitization = (str, config, fn) => {
str = str.trim() + "";
if (fn) {
return fn(str);
}
if (!str) {
return "";
}
............
}
配置解析与默认值设定
- 从 config 中解构出 before (脱敏前保留的字符数)和 after (脱敏后保留的字符数),并提供了默认值 0 。同时获取 type (数据类型标识,如 phone 、email 等)和 ch (用于替换敏感字符的符号,默认为
*
)。 - 根据不同的 type ,对 before 和 after 进行了智能的默认值调整。例如对于 phone 类型,若字符串长度小于 11 ,则合理调整 before 为 2,after 为 2,以适配常见的手机号码格式;对于 email 类型,则根据 @ 符号分割字符串来确定 after 的值,精准定位域名部分进行保护。
javascript
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;
}
构造正则进行脱敏
计算出需要显示的真实字符数 show ,基于此构建正则表达式 reg 。通过 replace 方法,按照正则表达式的匹配规则,用指定的 ch 符号替换中间的敏感字符,最终返回脱敏后的字符串。
javascript
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]);
指令执行函数
参数提取与初始值获取
从指令绑定的值 binding.value 中提取出 params ,进一步解构得到 config 和 fn 。同时获取元素 el 的相关属性值,如 innerHTML 、getAttribute 获取的原始值 originVal ,并初始化 inputOriginVal,为后续处理用户输入做准备。
javascript
const params = binding.value || {};
const { config, fn } = params;
let inputOriginVal = "";
let originVal = el.getAttribute("desensitization-originVal") || "";
文本节点脱敏处理
当 el.innerHTML 存在时,意味着是对页面展示的文本内容进行脱敏。首先确保 originVal 的获取,若为空则从 el.innerText 中获取并设置为原始值,存储在自定义属性 desensitization-originVal 中,然后调用 desensitization 函数对 originVal 进行脱敏处理,并更新 el.innerHTML。
javascript
if (el.innerHTML) {
if (!originVal) {
el.setAttribute("desensitization-originVal", el.innerText);
originVal = el.innerText;
}
el.innerHTML = desensitization(originVal, config, fn);
return;
}
输入框交互处理
针对输入框元素,先移除之前可能存在的焦点和失焦事件监听器,避免重复绑定。然后分别为 focus 和 blur 事件添加监听器。在 focus 事件中,将输入框的值恢复为原始输入值 inputOriginVal ;在 blur 事件中,获取当前输入值 value ,更新 inputOriginVal ,并调用 desensitization 函数对 value 进行脱敏处理,最后更新输入框的显示值。
javascript
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
当指令首次绑定到元素上时执行。在此处调用 doDesensitization 函数,尝试进行脱敏处理,若出现错误则捕获并打印 bindErr 相关的错误信息,确保指令初始化的稳定性。
javascript
bind: function (el, binding) {
try {
doDesensitization(el, binding);
} catch (err) {
console.error("bindErr", err);
}
}
update
当指令所在组件的数据更新时触发。首先判断元素 el 的 innerText 是否存在,若存在则调用 doDesensitization 函数进行重新脱敏处理,同样对错误进行捕获并打印 updateErr,保证数据更新后的脱敏效果持续有效。
javascript
update: function (el, binding) {
if (!el.innerText) return;
try {
doDesensitization(el, binding);
} catch (err) {
console.error("updateErr", err);
}
}
unbind
当指令从元素上移除时执行。主要任务是移除之前绑定的焦点和失焦事件监听器。
javascript
unbind: function (el) {
if (fouceListerner) {
el.removeEventListener("focus", fouceListerner);
}
if (blurListerner) {
el.removeEventListener("blur", blurListerner);
}
}
指令使用
电话号码脱敏
内置有电话的脱敏类型,对于11位数的手机号码,脱敏方式是显示前3位和后4位;对于小于11位数的,比如7位数的电话号码,脱敏方式是显示前2位和后2位。
html
<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>
身份证号码脱敏
内置有身份证号码的脱敏类型,脱敏方式是显示前3位和后4位;
html
<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>
姓名脱敏
内置有姓名的脱敏类型,两个字的姓名脱敏方式是显示第1位;大于两个字的姓名脱敏方式是显示第一个字和最后一个字。
html
<div class="content">
<input
v-JDesensitization:params="params"
placeholder="输入需要脱敏的字符"
class="input-content"
/>
<div v-JDesensitization:params="params" class="div-content">
张三风
</div>
</div>
<script>
export default{
data(){
return {
params:{
"config": {
"type": "name",
"before": ,
"after": "",
"ch": "*"
},
"fn": ""
},
}
}
}
</script>
邮箱脱敏
内置有邮箱的脱敏类型,脱敏方式是显示第一位和@
及以后的字符。
html
<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 参数即可自定义脱敏代替字符
javascript
params: {
config: {
type: "phone",
before: "",
after: "",
ch: "~",
},
fn: "",
}
- 可以自定义脱敏字符头尾显示位数
修改 config 中的 before 和 after 参数即可自定义脱敏显示位数,type 需要修改为内置类型以外的,直接传空即可。
javascript
params: {
config: {
type: "",
before: "2",
after: "2",
ch: "~",
},
fn: "",
}
- 可以自定义脱敏函数进行脱敏
可以直接在参数的 fn 中传入一个脱敏函数,如果传入了 fn ,其优先级最高,则其他参数都不会生效,会直接调用传入的 fn函数 进行脱敏,如:
javascript
(str) => {
return str[0] + '@'.repeat(str.length - 1);
}
应用场景
用户信息填写,输入框聚焦时显示真实数据 供用户进行修改,失焦时显示脱敏后的数据。
(至于为什么会有这个场景,需要去问一下产品经理😏)
组件库
组件文档
目前该指令也已经收录到我的组件库,组件文档地址如下: jyeontu.xyz/jvuewheel/#...
组件内容
组件库中还有许多好玩有趣的指令,如:
- 千分位分隔
- 防抖指令
- 拖拽指令
- 缩放指令
- 数字转大写中文
等等......
组件库源码
组件库已开源到gitee,有兴趣的也可以到这里看看:gitee.com/zheng_yongt...
🌟觉得有帮助的可以点个star~
🖊有什么问题或错误可以指出,欢迎pr~
📬有什么想要实现的组件或想法可以联系我~
公众号
关注公众号『前端也能这么有趣
』,获取更多有趣内容。
发送『组件库
』获取源码
说在后面
🎉 这里是 JYeontu,现在是一名前端工程师,有空会刷刷算法题,平时喜欢打羽毛球 🏸 ,平时也喜欢写些东西,既为自己记录 📋,也希望可以对大家有那么一丢丢的帮助,写的不好望多多谅解 🙇,写错的地方望指出,定会认真改进 😊,偶尔也会在自己的公众号『
前端也能这么有趣
』发一些比较有趣的文章,有兴趣的也可以关注下。在此谢谢大家的支持,我们下文再见 🙌。
最后的最后
最后再给自己拉个票,还有票的大佬们可以投我一票,感谢大家🥰🥰🥰
掘金2024年度人气创作者打榜中,快来帮我打榜吧~ activity.juejin.cn/rank/2024/w...