前置知识
selectionStart、selectionEnd
获取输入框光标的起始位置
效果
- 当不是选中时,两个值是一致的。
- 值是 0、1、2...(可以理解为当前位置前的长度)
setSelectionRange
可以设置光标的位置
setSelectionRange(selectionStart, selectionEnd)
效果预览
这是使用 element-plus 做出的,如果是原生的监听 input 事件即可,不用事件捕获了
代码:
<template>
<div class="main">
<h2>输入框动态加敏</h2>
<el-input
clearable
placeholder="请输入"
v-model="formModel.encryptValue"
@input.capture="handleEncryptValue($event)"
>
</el-input>
<p>原始值:{{ formModel.value }}</p>
</div>
</template>
<script setup>
import { onMounted, reactive, nextTick } from "vue";
let formModel = reactive({
value: "",
encryptValue: "",
});
// 思路:比对当前输入框的值与上一次的值的长度,可以判断出长度是否变化以及的变化的长度
// 如果是新增,原始值插入新增的值
// 如果是删除,原始值删除变化的长度
async function handleEncryptValue(event) {
let target = event.target;
// 获取位置
const selectionStart = target.selectionStart;
// 上一次的值与当前值
let prevValue = formModel.value;
const curValue = target.value;
// 判断是新增还是删除,以及变化的长度
let changeLen = curValue.length - prevValue.length;
const isAdd = changeLen > 0;
const num = Math.abs(changeLen);
let value = "";
if (isAdd) {
// 比如从 123 变成了 1243 我们就需要从 2 这个位置进行截取处理
value =
prevValue.slice(0, selectionStart - num) +
curValue.slice(selectionStart - num, selectionStart) +
prevValue.slice(selectionStart - num);
} else {
value =
prevValue.slice(0, selectionStart) +
prevValue.slice(selectionStart + num);
}
formModel.value = value;
formModel.encryptValue = formatter(value);
await nextTick();
if (target.setSelectionRange) {
target.setSelectionRange(selectionStart, selectionStart);
}
}
// 格式化
function formatter(value, rule = "x****xxxx") {
let valueList = value.split("");
let ruleList = rule.split("");
return valueList
.map((item, index) => {
return ruleList[index] === "*" ? "*" : item;
})
.join("");
}
</script>
<style scoped>
.main {
width: 400px;
height: 400px;
margin: 100px auto;
}
</style>