定义组件
// EditableInput.vue
<script setup>
import { ref, onMounted, onUnmounted, computed, reactive, useSlots, nextTick } from 'vue'
const props = defineProps({
modelValue: {
type: String,
default: ''
},
clearable: {
type: Boolean,
default: true
}
});
const slots = useSlots();
const emit = defineEmits(['update:modelValue', 'blur', 'focus']);
const handleInput = (value) => {
console.log('监听变化', value);
emit('update:modelValue', value);
};
const isEditing = ref(false);
const inputRef = ref(null);
const editRef = ref(null);
const updateText = (event) => {
text.value = event.target.value;
console.log('text.value', text.value);
};
const onFocus = () => {
inputRef.value?.focus();
};
const documentClickHandler = (event) => {
if (!isEditing.value && editRef.value?.contains(event.target)) {
console.log('如果点击的是输入框元素,则进入编辑模式', editRef.value);
isEditing.value = true;
nextTick(() => {
inputRef.value?.$el.querySelector('.el-input__inner')?.focus();
});
} else if (isEditing.value && !inputRef.value?.$el.querySelector('.el-input__inner').contains(event.target)) {
console.log('如果点击的不是输入框本身或其子元素,则退出编辑模式', inputRef.value);
isEditing.value = false;
}
};
onMounted(() => {
document.addEventListener('click', documentClickHandler);
});
onUnmounted(() => {
document.removeEventListener('click', documentClickHandler);
});
</script>
<template>
<div :class="{ editable: !isEditing }" @dblclick="toggleEditMode" ref="editRef">
<span v-if="!isEditing" contenteditable="false">{{ modelValue }}</span>
<el-input v-else :model-value="modelValue" @input="handleInput" :clearable="clearable" v-bind="$attrs"
@blur="$emit('blur', $event)" @focus="$emit('focus', $event)" ref="inputRef" class="input-style">
<template v-for="(slot, slotName) in slots" #[slotName]="slotProps">
<slot :name="slotName" v-bind="slotProps"></slot>
</template>
</el-input>
</div>
</template>
<style scoped>
.editable {
width: 100%;
height: 30px;
box-sizing: border-box;
padding: 4px;
border: 1px solid #ccc;
border-radius: 4px;
}
</style>
使用组件
<script setup>
import { EditableInput } from '@/components/ui'
</script>
<template>
<EditableInput v-model="scope.row.num" @blur="inputNum(scope.row, scope.$index)" onkeyup="value=value.replace(/[^0-9.]/g,'')" @input="handleChange" :clearable="false" />
</template>