数字键盘组件

贺波
2023-12-01

numPad.vue

<template>
  <div class="num-pad" :class="{ 'num-pad--visible': visible }">
    <div class="num-pad__header" v-if="withHeader">
      <span>{{ header }}</span>
      <button class="num-pad__close" @click="handleClose">X</button>
    </div>
    <div class="num-pad__body">
      <div v-for="(row, index) in rows" :key="index" class="num-pad__row">
        <div v-for="(num, index) in row" :key="index" class="num-pad__item" @click="handleClick(num)">
          {{ num }}
        </div>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  name: 'NumPad',
  props: {
    value: [Number, String],
    point: Boolean,
    withHeader: Boolean,
    header: String,
    visible: Boolean
  },
  data() {
    return {
      rows: [],
      canDelete: false
    }
  },
  created() {
    // 初始化数字键盘
    this.initRows();
  },
  methods: {
    initRows() {
      const { point } = this;
      if (point) {
        this.rows = [
          [1, 2, 3],
          [4, 5, 6],
          [7, 8, 9],
          ['.', 0, '<']
        ];
      } else {
        this.rows = [
          [1, 2, 3],
          [4, 5, 6],
          [7, 8, 9],
          ['', 0, '<']
        ];
      }
    },
    handleClick(num) {
      const { canDelete } = this;
      const { point } = this;
      const value  = this.value.toString();
      if (num === '') {
        return;
      }
      if (num === '.') {
        if (!value.includes('.') && point) {
          this.$emit('input', value + num);
          this.canDelete = true;
        }
      } else if (num === '<') {
        if (canDelete) {
          this.$emit('input', value.slice(0, -1));
          this.canDelete = value.length > 1;
        }
      } else if (value === '') {
        this.$emit('input', num);
        this.canDelete = true;
      } else {
        this.$emit('input', value + num);
        this.canDelete = true;
      }
    },
    handleClose() {
      this.$emit('update:visible', false);
    }
  },
  watch: {
    visible(newVal) {
      if (newVal) {
        this.canDelete = this.value !== '';
      }
    }
  }
}
</script>

<style rel="stylesheet/scss" lang="scss" scoped>
.num-pad {
  display: flex;
  flex-wrap: wrap;
  width: 250px;
  background-color: #fff;
  box-shadow: 0 1px 5px rgba(0,0,0,.2);
  position: fixed;
  bottom: 0;
  left: 50%;
  transform: translateX(-50%);
  transition: all .3s ease-out;
  z-index: 10;
  opacity: 0;
  &.num-pad--visible {
    transform: translateX(-50%) translateY(-100%);
    opacity: 1;
  }
  .num-pad__header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 0 10px;
    height: 40px;
    width: 100%;
    font-size: 18px;
    border-bottom: 1px solid #ccc;
    background-color: #f6f7f9;
  }
  .num-pad__body {
    display: flex;
    flex-wrap: wrap;
    justify-content: space-between;
    height: 250px;
    width: 100%;
    padding: 10px;
  }
  .num-pad__row {
    display: flex;
    justify-content: space-between;
    width: 100%;
    margin-bottom: 10px;
  }
  .num-pad__item {
    width: 30%;
    height: 50px;
    display: flex;
    justify-content: center;
    align-items: center;
    border: 1px solid #ccc;
    font-size: 24px;
    cursor: pointer;
    &:active {
      background-color: #f6f7f9;
    }
  }
  .num-pad__close {
    font-size: 24px;
    color: #999;
    border: none;
    background-color: transparent;
    cursor: pointer;
    &:focus,
    &:hover {
      color: #444;
    }
  }
}
</style>

使用 <num-pad v-model="form.number" :visible.sync="numPadVisible" point withHeader header="请输入数量" />

 类似资料: