效果如图:
代码:
// 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>