<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>