value-input.vue 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. <template>
  2. <div class="values-chose">
  3. <div class="values">
  4. <!-- 显示当内的多个值,用','连接多个值 -->
  5. <el-input
  6. class="values-show"
  7. size="small"
  8. readonly
  9. :model-value="props.modelValue.join(',')"
  10. ></el-input>
  11. </div>
  12. <div class="values-input">
  13. <template v-for="(tag, index) in tags" :key="tag">
  14. <!-- 编辑值 -->
  15. <el-input
  16. v-if="editIndex === index"
  17. v-model="editInputValue"
  18. class="value value-edit"
  19. size="small"
  20. @blur="handleEditConfirm"
  21. @keydown.enter="handleEditConfirm"
  22. ></el-input>
  23. <!-- 显示值 -->
  24. <el-tag
  25. v-else
  26. class="value"
  27. closable
  28. :disable-transitions="false"
  29. @close="handleClose(index)"
  30. @click="handleEdit(index)"
  31. >{{ tag }}</el-tag
  32. >
  33. </template>
  34. <!-- 点击新增显示输入框,否则显示新增按钮 -->
  35. <el-input
  36. v-if="inputVisible"
  37. ref="inputRef"
  38. v-model="inputValue"
  39. class="value-input"
  40. size="small"
  41. @blur="handleInputConfirm"
  42. @keydown.enter="handleInputConfirm"
  43. ></el-input>
  44. <el-button v-else size="small" @click="showInput"> + 新增值 </el-button>
  45. </div>
  46. </div>
  47. </template>
  48. <script lang="ts" setup>
  49. import { computed, nextTick, ref } from 'vue'
  50. import { ElButton, ElInput, ElTag } from 'element-plus'
  51. const props = defineProps({ modelValue: { type: Array<string>, required: false, default: '' } })
  52. const emit = defineEmits<{ 'update:modelValue': [values: string[]] }>()
  53. const tags = computed({
  54. get: () => {
  55. return props.modelValue ? props.modelValue : []
  56. },
  57. set: (values) => {
  58. emit('update:modelValue', values)
  59. }
  60. })
  61. // 编辑值
  62. const editIndex = ref(-1)
  63. const editInputValue = ref('')
  64. // 点击值标签,显示输入框编辑值
  65. const handleEdit = (index: number) => {
  66. editInputValue.value = tags.value[index]
  67. editIndex.value = index
  68. }
  69. // 编辑值输入框确认
  70. const handleEditConfirm = () => {
  71. if (editInputValue.value === tags.value[editIndex.value]) {
  72. return
  73. }
  74. tags.value[editIndex.value] = editInputValue.value
  75. tags.value = [...tags.value]
  76. editIndex.value = -1
  77. }
  78. // 点击值标签的右上角触发删除值
  79. const handleClose = (index: number) => {
  80. tags.value.splice(index, 1)
  81. tags.value = [...tags.value]
  82. }
  83. // 新增值
  84. const inputRef = ref<InstanceType<typeof ElInput>>()
  85. const inputVisible = ref(false)
  86. const inputValue = ref('')
  87. const handleInputConfirm = () => {
  88. if (inputValue.value) {
  89. tags.value = [...tags.value, inputValue.value]
  90. }
  91. inputVisible.value = false
  92. inputValue.value = ''
  93. }
  94. const showInput = () => {
  95. inputVisible.value = true
  96. nextTick(() => {
  97. if (inputRef.value && inputRef.value.input) {
  98. inputRef.value.input.focus()
  99. }
  100. })
  101. }
  102. </script>
  103. <style lang="scss" scoped>
  104. .values {
  105. display: flex;
  106. justify-content: flex-start;
  107. .values-show {
  108. width: 100px;
  109. }
  110. }
  111. .values-input {
  112. margin-top: 10px;
  113. display: flex;
  114. align-items: center;
  115. flex-wrap: wrap;
  116. margin-bottom: 10px;
  117. .value-edit {
  118. width: 100px;
  119. }
  120. .value {
  121. margin-right: 5px;
  122. }
  123. .value-input {
  124. width: 100px;
  125. }
  126. }
  127. </style>