用vue3封装Arco design Table行内步进器

792 阅读1分钟

效果如图:

image.png 代码:

// ChangeQty.vue
<template>
  <div>
    <a @click="reduceQty">-</a>
    <input
      type="text"
      v-model="inputValue"
      @input="inputQty"
    />
    <a @click="increaseQty">+</a>
  </div>
</template>


<*  
   说明:
    最初的方案是:value="qty",但用value=""的方式并不能数据响应;
    输入文字的时候qty已经变成0,但是input框中依旧是显示文字。。。
    试试:value="inputValue"就知道,但是又不能v-model="qty",只能用一个中间值来实现
*>

<script lang="ts" setup>
...
const props = defineProps({
  // 选中行的步进器数量
  qty: {
    type: Number,
    default: 0,
  },
  min: {
    type: Number,
    default: 0,
  },
});

const emits = defineEmits<{
  (event: "change", value: number): void;
}>();

// 步进器本身的值
const inputValue = ref(0);

// 加
const increaseQty = () => {
  inputValue.value++;
};

// 减
const reduceQty = () => {
  if (inputValue.value <= props.min) return;
  inputValue.value--;
};

// 输入修改
const inputQty = (e: any) => {
  let value = e.target?.value;
  const { min } = props;
  if (value.length <= 1) {
    const reg = new RegExp("[^" + min + "-9]", "g");
    value = value.replace(reg, min);
  } else {
    value = +value.replace(/\D/g, "");
  }
  // 防止:输入文字会多次触发oninput且有些时候value不存在或者等于0
  if (!+value) {
    value = min;
  }
  inputValue.value = +value;
};

watch(
  () => inputValue.value,
  () => {
    if (inputValue.value === props.qty) return;
    // 更新表格qty
    emits('change', inputValue.value);
  }
);

// 这里是勾选 input框值变成1
watch(
  () => props.qty,
  () => {
    if (inputValue.value === props.qty) return;
    inputValue.value = props.qty;
  },
  {
    immediate: true
  }
);
</script>

<style lang="less">
    ...
</style>
// vuex

  getters: {
    tableSelectedRows(state) {
      return state.bagData?.map(i => i.id);
    }
  },
// Table.vue
<template>
// Arco design
  <a-table
    ...
    :selectedKeys="getters.tableSelectedRows"
  >
    <template #action="{ record }">
      <div>
        <ChangeQty :qty="record.bagQty" @change="v => onQtyChange(v, record)" />
         ...
      </div>
    </template>
  </a-table>
</template>

<script lang="ts" setup>
    // 思路:通过监听input框的值来同步每一行的数量,并控制是否选中
    const onQtyChange = (value: number, record: any) => {
       record.bagQty = value;
       if (value <= 0) {
         // 如果在选中状态下输入0,则取消勾选
         commit('removeItemBagData', record);
       } else {
         commit('addItemBagData', record);
       }
    };
</script>

<style lang="less">
    ...
</style>