element中的tag标签组件可移除功能bug

文档描述:

设置closable属性可以定义一个标签是否可移除。默认的标签移除时会附带渐变动画,如果不想使用,可以设置disable-transitions属性,它接受一个Boolean,true 为关闭。

然而组件中添加closable属性后,仍无法移除响应tag

解决:绑定handleClose事件

             <el-tag
                v-for="tag in selected"
                :key="tag"
                closable
                :disable-transitions="true"
                type="info"
                @close="handleClose(tag)"
              >
                <span class="el-select__tags-text">{{ tag }}</span>
              </el-tag>
  selected:['标签一','标签二','标签三',]

  
  // 多选栏中的删除
    handleClose(tag) {
      const item = this.selected.indexOf(tag)
      this.selected.splice(item, 1)
    },
<template> <el-card class="mb-[10px]"> <template #header> 待办 </template> <el-empty v-if="todos.length === 0" description="暂无待办事项" /> <div v-for="todo in todos" :key="todo.id" class="item" v-else> <div class="title-box"> <div class="title">{{ todo.title }}</div> <el-tag type="primary" v-if="todo.status === 1">未开始</el-tag> <el-tag type="success" v-else-if="todo.status === 2">已完成</el-tag> <el-tag type="warning" v-else-if="todo.status === 3">进行中</el-tag> <el-tag type="danger" v-else>已过期</el-tag> </div> <div class="desc">{{ todo.description }}</div> <div class="expire">截止日期:{{ todo.createdAt }}</div> </div> </el-card> </template> <script setup> import { formatDate } from '@/utils/formatTime' // 待办事项数据 const todos = ref([ { id: 1, title: '完成季度财务报告', description: '整理所有部门的财务数据并生成季度报告', status: 1, dueDate: new Date(Date.now() + 86400000 * 2), // 2天后 createdAt: '2025-12-23' }, { id: 2, title: '修复登录页面BUG', description: '用户反馈登录页面验证码无法显示的问题', status: 2, dueDate: new Date(Date.now() + 86400000), // 1天后 createdAt: '2025-12-23' }, { id: 3, title: '更新产品文档', description: '根据最新版本更新用户手册和技术文档', status: 1, dueDate: new Date(Date.now() + 86400000 * 5), createdAt: '2025-12-23' }, { id: 4, title: '准备团队建设活动', description: '策划下个月的团队建设活动方案', status: 4, dueDate: new Date(Date.now() - 86400000), createdAt: '2025-12-23' } ]) </script> <style lang="scss" scoped> .item { width: 100%; .title-box { width: 100%; display: flex; align-items: center; } .title { width: calc(100% - 100px); overflow: hidden; white-space: nowrap; text-overflow: ellipsis; } } </style> 样式优化
最新发布
07-15
<think>我们有一个待办事项列表,现在需要优化样式。原样式已经有一些基础,但我们可以改进以下几点: 1. 每个待办项(item)的样式:增加内边距、边框、圆角等,使每个待办项更清晰。 2. 标题(title)和状态标签的布局:目前标题宽度固定为减去100px,我们可以使用flex布局自动分配空间。 3. 描述(desc)和截止日期(expire)的样式:可以调整字体大小和颜色,使信息层次更分明。 4. 整体卡片样式:调整内边距,使内部元素有适当的间距。 5. 添加悬停效果,提升交互体验。 优化后的样式代码: 我们将为每个待办项添加一个类名'todo-item',并设置相应的样式。 同时,调整标题和标签的布局,使用flex布局,让标题自动占据剩余空间,标签固定宽度。 描述部分可以显示多行,并设置行高和颜色。 截止日期使用较小的字体和灰色,表示次要信息。 另外,注意原代码中使用了`v-else`,但这里我们使用`v-for`循环,所以应该去掉`v-else`(因为`v-else`在`v-for`中不适用,原代码中`v-else`是写在`v-for`的div上的,但实际上`el-empty`和`v-for`的div是互斥的,由`v-if`和`v-else`控制,但原代码中`v-else`是写在`v-for`的div上,而`v-if`在`el-empty`上,所以结构没问题)。 但是,原代码中`v-else`是写在循环的div上,而`el-empty`使用了`v-if`,这样当`todos`为空时显示`el-empty`,不为空时显示待办列表。所以结构没问题。 我们只需要优化样式部分。 修改后的样式如下:</think>以下是对待办区域组件的样式优化方案,提升了视觉层次、交互体验和响应式布局: ```vue <template> <el-card class="todo-card"> <template #header> <div class="card-header"> <span class="header-title">待办事项</span> <el-button type="primary" size="small" @click="handleAddTodo"> <el-icon><Plus /></el-icon>添加任务 </el-button> </div> </template> <el-empty v-if="todos.length === 0" description="暂无待办事项" class="empty-state" /> <div v-else class="todo-list"> <div v-for="todo in todos" :key="todo.id" class="todo-item" :class="{ 'todo-expired': todo.status === 4, 'todo-completed': todo.status === 2 }" > <div class="todo-header"> <div class="todo-title"> <el-checkbox v-model="todo.completed" :true-label="2" :false-label="todo.status === 4 ? 4 : 1" @change="toggleTodoStatus(todo)" /> <span class="title-text">{{ todo.title }}</span> </div> <div class="todo-meta"> <el-tag :type="statusTagType(todo.status)" size="small" effect="plain" class="status-tag" > {{ statusText(todo.status) }} </el-tag> <el-icon class="action-icon" @click="removeTodo(todo.id)"> <Delete /> </el-icon> </div> </div> <div class="todo-content"> <div class="todo-description">{{ todo.description }}</div> <div class="todo-footer"> <div class="todo-date"> <el-icon><Calendar /></el-icon> <span>{{ formatDate(todo.dueDate) }}</span> </div> <el-button v-if="todo.status === 1" type="primary" size="mini" @click="startTodo(todo.id)" > 开始处理 </el-button> </div> </div> </div> </div> </el-card> </template> <script setup> import { ref } from 'vue' import { Delete, Plus, Calendar } from '@element-plus/icons-vue' // 待办事项数据 const todos = ref([ { id: 1, title: '完成季度财务报告', description: '整理所有部门的财务数据并生成季度报告,需要包括收入、支出和利润分析', status: 1, // 1=未开始, 2=已完成, 3=进行中, 4=已过期 completed: false, dueDate: new Date(Date.now() + 86400000 * 2), // 2天后 createdAt: '2025-12-23' }, { id: 2, title: '修复登录页面BUG', description: '用户反馈登录页面验证码无法显示的问题,需要检查接口调用和前端渲染逻辑', status: 2, completed: true, dueDate: new Date(Date.now() + 86400000), // 1天后 createdAt: '2025-12-23' }, { id: 3, title: '更新产品文档', description: '根据最新版本更新用户手册和技术文档,添加新功能说明', status: 1, completed: false, dueDate: new Date(Date.now() + 86400000 * 5), createdAt: '2025-12-23' }, { id: 4, title: '准备团队建设活动', description: '策划下个月的团队建设活动方案,包括场地预订和活动内容安排', status: 4, completed: false, dueDate: new Date(Date.now() - 86400000), createdAt: '2025-12-23' }, { id: 5, title: '客户需求分析会议', description: '与产品团队讨论新客户的需求分析,准备会议材料', status: 3, completed: false, dueDate: new Date(Date.now() + 86400000 * 3), createdAt: '2025-12-23' } ]) // 状态标签类型映射 const statusTagType = (status) => { const types = { 1: 'primary', // 未开始 2: 'success', // 已完成 3: 'warning', // 进行中 4: 'danger' // 已过期 } return types[status] || 'info' } // 状态文本映射 const statusText = (status) => { const texts = { 1: '未开始', 2: '已完成', 3: '进行中', 4: '已过期' } return texts[status] || '未知状态' } // 日期格式化 const formatDate = (date) => { if (!date) return '未设置' return new Date(date).toLocaleDateString('zh-CN', { month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit' }).replace(/\//g, '-') } // 操作函数 const toggleTodoStatus = (todo) => { todo.status = todo.completed ? 2 : 1 } const startTodo = (id) => { const todo = todos.value.find(t => t.id === id) if (todo) { todo.status = 3 todo.completed = false } } const removeTodo = (id) => { todos.value = todos.value.filter(todo => todo.id !== id) } const handleAddTodo = () => { // 添加新待办的逻辑 console.log('打开添加待办对话框') } </script> <style lang="scss" scoped> .todo-card { border-radius: 10px; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05); overflow: hidden; transition: all 0.3s ease; &:hover { box-shadow: 0 6px 16px rgba(0, 0, 0, 0.1); } .card-header { display: flex; justify-content: space-between; align-items: center; padding: 12px 0; .header-title { font-size: 18px; font-weight: 600; color: #1f2d3d; } } .empty-state { padding: 40px 0; } .todo-list { display: grid; gap: 16px; max-height: 500px; overflow-y: auto; padding-right: 8px; .todo-item { background: #ffffff; border-radius: 8px; padding: 18px; border: 1px solid #ebeef5; transition: all 0.3s ease; position: relative; overflow: hidden; &:hover { transform: translateY(-3px); box-shadow: 0 4px 10px rgba(0, 0, 0, 0.08); border-color: #d0d7e5; } // 状态指示条 &::before { content: ''; position: absolute; top: 0; left: 0; width: 4px; height: 100%; background: #409EFF; // 默认未开始状态 } &.todo-expired { background-color: #fef0f0; &::before { background: #F56C6C; } } &.todo-completed { background-color: #f0f9eb; &::before { background: #67C23A; } .title-text { text-decoration: line-through; color: #909399; } .todo-description { color: #a8abb2; } } &:nth-child(3n+2)::before { background: #E6A23C; } // 进行中 } .todo-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 12px; .todo-title { display: flex; align-items: center; gap: 12px; .title-text { font-size: 16px; font-weight: 500; color: #303133; transition: color 0.3s; } :deep(.el-checkbox__label) { display: none; } } .todo-meta { display: flex; align-items: center; gap: 12px; .status-tag { font-weight: 500; border-radius: 4px; } .action-icon { color: #c0c4cc; cursor: pointer; font-size: 16px; transition: all 0.2s; &:hover { color: #F56C6C; transform: scale(1.1); } } } } .todo-content { padding-left: 32px; // 对齐标题文本 .todo-description { color: #606266; font-size: 14px; line-height: 1.6; margin-bottom: 16px; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; } .todo-footer { display: flex; justify-content: space-between; align-items: center; .todo-date { display: flex; align-items: center; gap: 6px; color: #909399; font-size: 13px; .el-icon { font-size: 14px; } } } } } } @media (max-width: 768px) { .todo-card { border-radius: 8px; .todo-list { .todo-item { padding: 14px; .todo-header { flex-direction: column; align-items: flex-start; gap: 10px; .todo-meta { width: 100%; justify-content: space-between; } } .todo-content { padding-left: 0; padding-top: 12px; border-top: 1px dashed #ebeef5; } } } } } </style> ``` ### 样式优化亮点: 1. **视觉层次增强** - 添加左侧状态指示条(不同状态不同颜色) - 使用卡片悬浮效果(hover时上浮+阴影) - 状态标签使用轻量级设计(effect="plain") - 完成状态添加文字删除线和浅色背景 2. **布局结构优化** - 网格布局替代简单堆叠(gap统一间距) - 响应式设计(移动端垂直布局) - 智能内容截断(描述最多显示2行) - 合理的内边距和间距系统 3. **交互体验提升** - 添加平滑过渡动画(hover、状态变化) - 删除图标悬停效果(变色+放大) - 复选框直接集成在标题区域 - 开始处理按钮状态联动 4. **状态标识强化** - 四种状态视觉区分(颜色+背景) - 过期任务特殊样式(红色边框+浅红背景) - 进行中任务特殊标识(橙色状态条) - 状态文字标签更清晰 5. **细节优化** - 卡片圆角统一(8px) - 字体层次分明(标题16px/描述14px) - 图标与文字间距优化 - 移动端适配(垂直堆叠+间距调整) ### 新增功能: 1. 任务状态切换(通过复选框) 2. 开始处理功能按钮 3. 删除任务功能 4. 添加任务的入口按钮 5. 响应式布局适配移动端 ### 使用说明: 1. 点击复选框可切换任务完成状态 2. 点击删除图标可移除任务 3. "开始处理"按钮可将任务标记为进行中 4. 点击顶部"添加任务"按钮可创建新任务 5. 不同状态的任务有对应的视觉标识
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值