<template> <div class="password-number" :class="{ gutter: gutter != 0 }"> <div class="password-item" :class="{ gutter: gutter != 0 }" :style="{ margin: `0 ${gutter}px` }" v-for="(item, index) in length" :key="index" > <input class="password-input" @input="_input" @keyup="_keyup" :type="!password ? 'number' : 'text'" :ref="`passwordIndex${index}`" :value="!password ? code[index] : passwordViewCode[index]" :maxlength="1" v-max-length="{ password, mark }" /> </div> <div class="mantle" @click="setFocus"></div> </div></template><script>export default { data() { return { code: "", passwordViewCode: "", }; }, props: { //明码数量 length: { type: Number, default: 6, }, //是否展现明文 password: { type: Boolean, default() { return false; }, }, //加密字符 mark: { type: String, default() { return "●"; }, }, //格子间距 gutter: { type: String, default() { return "0"; }, }, }, directives: { /** * 自定义指令 最大数量 */ maxLength: { bind(el, { value }) { el.oninput = () => { let str = el.value; if (el.value.length > 1) { if (str.length > 1) { el.value = value.password ? value.mark : str.charAt(0); } else { el.value = str.charAt(0); } } }; }, }, }, methods: { /** * 焦点赋值 */ setFocus() { let _length = this.code.length; if (_length < this.length) { this.$refs[`passwordIndex${_length}`][0].focus(); } else { this.$refs[`passwordIndex${_length - 1}`][0].focus(); } }, /** * 输出 */ _input(e) { if (e != null) { let str = e.data; if (/[^\d]/g.test(str)) { str = ""; this.$refs[`passwordIndex0`][0].value = str; } if (/^[0-9]+$/.test(str)) { if (this.code.length < this.length) { this.code += str; this.passwordViewCode += this.mark; this.setFocus(); } if (this.code.length == this.length) { this.$emit("change", this.code); } } } }, /** * 删除 */ _keyup(e) { if (e.keyCode == 8) { let str = this.code; this.code = str.substr(0, str.length - 1); let password_str = this.passwordViewCode; this.passwordViewCode = password_str.substr(0, password_str.length - 1); this.setFocus(); } }, /** * 重置数据 */ resetData() { this.code = ""; this.passwordViewCode = ""; }, },};</script><style lang="scss" scoped>.password-number { height: 40px; width: 400px; border: 1px solid #ddd; display: flex; position: relative; &.gutter { border: 0; } .mantle { position: absolute; top: 0; left: 0; width: 100%; height: 100%; cursor: pointer; } .password-item { flex: 1; position: relative; &::after { content: ""; display: block; width: 1px; height: 30px; background-color: #eee; position: absolute; top: 50%; transform: translateY(-50%); left: 0; } &:nth-child(1) { &::after { display: none; } } &.gutter { background-color: #eee; width: 40px; &::after { display: none; } } .password-input { width: 100%; height: 100%; text-align: center; display: flex; align-items: center; justify-content: center; background: none; border: 0; } }}</style>