前端-如何做一个关键字生成组件

效果示意图:

组件代码:

复制代码
<template>
  <div class="custom-tag">
    <input
      v-if="tag.editing"
      v-model="localText"
      @blur="handleBlur"
      @keyup.enter="handleBlur"
      @input="adjustInputWidth"
      ref="inputRef"
      class="tag-input"
    />
    <span v-else>{{ tag.text }}</span>
    <CloseOutlined @click="$emit('remove')" class="small-icon" />
  </div>
</template>

<script setup>
  import { ref, watch, nextTick } from 'vue';
  import { CloseOutlined } from '@ant-design/icons-vue';

  const props = defineProps({
    tag: {
      type: Object,
      required: true
    }
  });

  const emit = defineEmits(['update:tag', 'remove']);

  const localText = ref(props.tag.text);
  const editing = ref(props.tag.editing);
  const inputRef = ref(null);

  watch(
    () => props.tag.text,
    (newText) => {
      localText.value = newText;
    }
  );

  const handleBlur = () => {
    editing.value = false;
    emit('update:tag', {
      ...props.tag,
      text: localText.value,
      editing: editing.value
    });
  };

  const adjustInputWidth = () => {
    nextTick(() => {
      if (inputRef.value) {
        inputRef.value.style.width = `${inputRef.value.scrollWidth}px`;
      }
    });
  };
</script>

<style scoped>
  .custom-tag {
    display: flex;
    align-items: center;
    margin-right: 5px;
    background-color: #ff811a;
    border-radius: 4px;
    padding: 2px 5px;
    color: white;
  }

  .tag-input {
    border: none;
    background-color: #ff811a;
    padding: 0 5px;
    border-radius: 4px;
    color: white;
    outline: none; /* 去掉输入框聚焦时的默认边框 */
    width: 25px; /* 设置初始宽度 */
    min-width: 25px; /* 设置最小宽度 */
    box-sizing: border-box; /* 确保内边距和边框包含在宽度内 */
  }

  .small-icon {
    font-size: 0.5em; /* 将图标大小缩小为原来的一半 */
    cursor: pointer;
    color: white;
    margin-left: 5px; /* 增加一些间距,使图标更明显 */
  }

  .small-icon:hover {
    color: #ffcc00; /* 悬停时改变颜色 */
  }
</style>

父组件中使用方法:

复制代码
<div style="display: flex; margin-bottom: 5px">
          关键字:
          <tags
            v-for="(tag, index) in tagsList"
            :key="index"
            :tag="tag"
            @remove="removeTag(index)"
          />
          <div
            v-show="tagsList.length < 5"
            style="color: #ff811a"
            @click="addKey"
          >
            +关键字
          </div>
        </div>



  const addKey = () => {
    tagsList.value.push({ text: '', editing: true });
  };

  const removeTag = (index) => {
    console.log('tagsList', tagsList);
    tagsList.value.splice(index, 1);
  };
相关推荐
思码梁田3 分钟前
CSS display 属性:从元素类型转换到隐藏元素的实用指南
前端·css·display·inline·block·none·inline-block
Csvn4 分钟前
⚡ Vite 依赖预构建(optimizeDeps)的 3 个经典坑:改了源码不生效、新增依赖 404、缓存怎么清都不行
前端
A242073493014 分钟前
Vue3 + TypeScript:后端数据在表格内渲染后进行增删改的完整实现步骤
前端·javascript·typescript
他们叫我 悦儿遥遥雨18 分钟前
.NET 8 Web开发入门(六):Blazor 全栈开发——告别 JavaScript 焦虑
前端·javascript·.net
用户21816970493025 分钟前
Flutter(九)StatelessWidget StatefullWidget
前端
paopaokaka_luck25 分钟前
基于springboot3+vue3的乡村医生诊疗管理系统(AI助手、协同过滤算法、webSocket实时聊天、Echarts图形化分析)
前端·网络·人工智能·spring boot·websocket·网络协议·echarts
编程风暴26 分钟前
3类人群的数据分析实习类型选择+4条选错红线
java·前端·数据分析
其美杰布-富贵-李26 分钟前
Vue 3 模块导入教程:import、export 与文件组织
前端·javascript·vue.js
Bigger38 分钟前
堆了 20 套主题、10+ 组件,用户还是用不出来?我给设计 Skill 加了「自动驾驶」
前端·ai编程·视觉设计
weipt41 分钟前
springboot项目运行的几种方式
javascript·css·html