el-tabs添加按钮增加点击禁止样式
前置文章
一、vue使用element-ui自定义样式思路分享【实操】
二、vue3&ts&el-tabs多个tab表单校验
现状确认
- 点击添加按钮,没有点击样式,用户感知不明显
- 没有限制最大的tab添加数量,可以无限添加
调整目标&代码编写
调整目标
- 点击添加按钮,按钮背景变成蓝色,加号图标变成白色
- 限制最大的tab添加数量为
10
,超过10
添加按钮设置为灰色不可点击
代码编写
点击添加按钮,按钮背景变成蓝色
在vue使用element-ui自定义样式思路分享【实操】提到了如何给el-tabs按钮自定义样式,文本在按钮已经设置了自定义样式的基础上进行,首先实现点击按钮时,背景颜色变成蓝色,考虑使用伪类选择器active
来实现。
蓝色保持与element框架默认提供的一致,可以通过Snipaste来拾取:F1开启截屏,鼠标移动到蓝色区域,Shift切换颜色数据类型,按C完整复制。
代码调整如下
/*添加按钮点击显示蓝色*/
.asset-tab :deep(.el-tabs__new-tab):active {background: #409eff;
}
效果
点击添加按钮,加号图标变成白色
观察svg的样式选择器,观察到通过fill
设置颜色不生效,修改color
颜色才生效,例如下图中设置为红色
添加代码
/*设置svg点击颜色显示白色*/
.asset-tab :deep(.el-tabs__new-tab):active .is-icon-plus svg {color: white;
}
效果
js动态禁止按钮点击&设置按钮禁止样式
添加禁止样式(主要关注前面三行)
/*禁止样式*/
.asset-tab :deep(.el-tabs__new-tab.disabled) {pointer-events: none;opacity: 0.8;background: lightgray;height: 30px;width: 30px;border-radius: 15px;font-size: 16px;
}
操作document动态添加或去除禁止样式,注意document.querySelector()
选择器不需要加:deep()
,并将修改逻辑抽取成方法setAddBtnStatus
,在增减tab逻辑后调用即可
const setAddBtnStatus = function () {const newTab = document.querySelector('.asset-tab .el-tabs__new-tab')console.log('newTab', newTab)const index = tabs.value.lengthif (index >= 10) {newTab?.classList.add('disabled')} else {newTab?.classList.remove('disabled')}
}
最终效果&完整代码
完整代码:
<!--AssetCreate.vue-->
<template><div style="margin-bottom: 10px"><h3>数据源选择:</h3><el-switch v-model="isUseLocalFlag" active-text="使用本地服务数据" inactive-text="使用mock数据"/><el-button @click="setTabData" style="margin-left: 10px;">给tab赋值</el-button><el-button @click="clearTabData" >清空tab赋值</el-button></div><div class="asset-tab"><el-tabs v-model="activeTab" type="card" editable class="demo-tabs" @edit="handleTabsEdit"><el-tab-pane v-for="tab in tabs" :key="tab.name" :label="tab.label" :name="tab.name"><AssetItem ref="assetItemRefs" :insertForm="tab.insertForm"/></el-tab-pane></el-tabs></div><div class="bottom-btn"><el-button @click="submitAsset" type="primary">提交</el-button></div>
</template><script setup lang="ts">
import { ref } from 'vue'
import axios from 'axios'
import type { TabPaneName } from 'element-plus'
import { removeRedundantFields } from '@/utils/methodUtil'
import AssetItem from '@/components/asset/AssetItem.vue'
import type { AssetFormData } from '@/types'
import { ElMessage } from 'element-plus'
// 当前激活的tab
const activeTab = ref('表单 1')
// tabs初始数据
const tabs = ref([{ label: '表单 1', name: '表单 1', insertForm: {} }
])
const isUseLocalFlag = ref(true)
const clearTabData = function () {tabs.value = [{ label: '表单 1', name: '表单 1', insertForm: {} }]activeTab.value = '表单 1'setAddBtnStatus()
}
const setTabData = async function () {const bizId = '0777c40218114c35a29b0d4d84355668'if (isUseLocalFlag.value) {await axios.post(`/asset/assetInfo/${bizId}/byBizId`).then(result => {if (result.status === 200) {tabs.value = []const assetInfoList = result?.data?.data?.assetInfoListconst removeResult = removeRedundantFields(assetInfoList, ['extAttribute11', 'extAttribute12','extAttribute13', 'extAttribute14', 'extAttribute15', 'extAttribute16', 'extAttribute17', 'extAttribute18','extAttribute19', 'extAttribute20'])removeResult.forEach((item, index) => {const newTabName = `表单 ${index + 1}`tabs.value.push({label: newTabName,name: newTabName,insertForm: item})setAddBtnStatus()activeTab.value = newTabName})}})} else {// 请求mock数据await axios.post('/mock/asset/assetInfo', { bizId }).then(result => {const assetInfoList: Array<AssetFormData> = result?.data?.data?.assetInfoListtabs.value = []assetInfoList.forEach((asset, idx) => {const newTabName = `表单 ${idx + 1}`tabs.value.push({label: newTabName,name: newTabName,insertForm: asset})setAddBtnStatus()activeTab.value = newTabName})})}
}
const assetItemRefs = ref<InstanceType<typeof AssetItem>[]>([])
const handleTabsEdit = (targetName: TabPaneName | undefined,action: 'remove' | 'add'
) => {if (action === 'add') {let index = tabs.value.lengthif (index >= 10) returnconst newTabName = `表单 ${++index}`tabs.value.push({label: newTabName,name: newTabName,insertForm: {}})activeTab.value = newTabName} else if (action === 'remove') {const activeName = activeTab.valueif (tabs.value.length === 1) returntabs.value = tabs.value.filter((tab) => tab.name !== targetName)tabs.value.forEach((item, index) => {item.name = `表单 ${++index}`item.label = item.name})const currentExist = tabs.value.some((item, index) => {if (item.name === activeName) {return index}return false})if (!currentExist) activeTab.value = tabs.value[tabs.value.length - 1].name}setAddBtnStatus()
}
const setAddBtnStatus = function () {const newTab = document.querySelector('.asset-tab .el-tabs__new-tab')const index = tabs.value.lengthif (index >= 10) {newTab?.classList.add('disabled')} else {newTab?.classList.remove('disabled')}
}
const verifyPass = ref(true)
const submitAsset = async function () {for (const index in assetItemRefs.value) {const verifyResult = await assetItemRefs.value[index].submitForm()// 定位到第一个校验失败的tabif (!verifyResult) {verifyPass.value = falseactiveTab.value = `表单 ${Number(index) + 1}`break} else {verifyPass.value = true}}if (verifyPass.value) ElMessage({ message: '表单校验通过', type: 'success' })
}
</script><style scoped>
/*禁止样式*/
.asset-tab :deep(.el-tabs__new-tab.disabled) {pointer-events: none;opacity: 0.8;background: lightgray;height: 30px;width: 30px;border-radius: 15px;font-size: 16px;
}
.asset-tab :deep(.el-tabs__new-tab) {height: 30px;width: 30px;border-radius: 15px;font-size: 16px;
}/*添加按钮点击显示蓝色*/
.asset-tab :deep(.el-tabs__new-tab):active {background: #409eff;
}
/*设置svg点击颜色显示白色*/
.asset-tab :deep(.el-tabs__new-tab):active .is-icon-plus svg {color: white;
}
.bottom-btn {text-align: center;margin-bottom: 10px;
}
</style>
代码仓:hello_vue3
相关文章:
el-tabs添加按钮增加点击禁止样式
前置文章 一、vue使用element-ui自定义样式思路分享【实操】 二、vue3&ts&el-tabs多个tab表单校验 现状确认 点击添加按钮,没有点击样式,用户感知不明显没有限制最大的tab添加数量,可以无限添加 调整目标&代码编写 调整目标…...
Elasticsearch DSL 中的 aggs 聚合
一、聚合的概述 Elasticsearch 的 聚合(Aggregations) 功能用于对数据进行多维分析和统计,支持从简单的指标计算到复杂的分组分析。以下是聚合的基本结构: {"aggs": { // 也可以使用"agg…...
API调用类型全面指南:理解基础知识
在当今快速发展的数字化环境中,API(应用程序编程接口)是不同软件应用程序能够无缝通信的基石。无论是开发移动应用、集成第三方服务,还是构建强大的Web平台,理解各种API调用类型至关重要。那么,API调用到底…...
华东师范地面机器人融合空中无人机视角的具身导航!KiteRunner:语言驱动的户外环境合作式局部-全局导航策略
作者:Shibo Huang 1 ^{1} 1, Chenfan Shi 1 ^{1} 1, Jian Yang 2 ^{2} 2, Hanlin Dong 1 ^{1} 1, Jinpeng Mi 3 ^{3} 3, Ke Li 2 ^{2} 2, Jianfeng Zhang 1 ^{1} 1, Miao Ding 4 ^{4} 4, Peidong Liang 5 ^{5} 5, Xiong You 2 ^{2} 2, Xian Wei 1 ^{1} 1单位&#x…...
Ansible(6)——管理变量
目录 一、Ansible 变量: 1、什么是变量: 2、变量可能包含的值: 3、变量命名: 4、定义变量: 二、Playbook 中的变量: 1、在 Playbook 中定义变量: (1)最简单的定…...
Git常用问题收集
gitignore 忽略文件夹 不生效 有时候我们接手别人的项目时,发现有的忽略不对想要修改,但发现修改忽略.gitignore后无效。原因是如果某些文件已经被纳入版本管理在.gitignore中忽略路径是不起作用的,这时候需要先清除本地缓存,然后…...
构建高效多标签选择组件:从设计到实现
在现代Web应用中,多标签选择功能已成为常见需求,特别是在内容分类、文章标签、用户兴趣选择等场景。本文将深入解析一个完整的多标签选择实现方案,涵盖交互设计、核心功能和优化技巧。 组件功能概述 这个多标签选择组件提供以下核心功能&am…...
4.1论文阅读
一:PhDnet:一种用于遥感图像的新型物理感知去雾网络(A novel physic-aware dehazing network for remote sensing images) 论文链接 只是粗略读了一下,关于遥感图像去雾,圆形U--net,加入了物理…...
【渗透测试】Vulnhub靶机-HA: Armour-详细通关教程
下载地址:https://www.vulnhub.com/entry/ha-armour,370/ 目录 前言 信息收集 tftp获取(spiderman) 查看.htpasswd(ant-man) ssh欢迎信息提示(hulkbuster) 反弹shell 提权(i…...
Flask使用MySQL数据库通过Flask-SQLAlchemy 迁移数据库,实际更新文件,但是提示没有检测到数据更新。
本地写了一个model的用户类,数据库连接信息正确,执行下面2条命令进行数据库迁移。 flask db migrate 生成迁移文件 flask db upgrade 执行迁移文件的升级 发现执行完后:提示没有检测到数据的更新 PS C:\Users\mu> flask db migrate IN…...
【leetcode100】前K个高频元素
1、题目描述 给你一个整数数组 nums 和一个整数 k ,请你返回其中出现频率前 k 高的元素。你可以按 任意顺序 返回答案。 示例 1: 输入: nums [1,1,1,2,2,3], k 2 输出: [1,2]示例 2: 输入: nums [1], k 1 输出: [1] 2、初始思路 2.1 思路 全排列…...
内网渗透-MySQL提权
MySQL提权 mysql的权限提升通常有两种: UDF提权(常用) 写文件提权启动项提权mof提权一、UDF提权 UDF 全称为user defined function,用户自定义函数 用户可以添加自定义的新函数到Mysql中,以达到功能的扩充…...
Hibernate核心方法总结
Session中的核心方法梳理 1、save方法 这个方法表示将一个对象保存到数据库中,可以将一个不含OID的new出来的临时对象转换为一个处于Session缓存中具有OID的持久化对象。 需要注意的是:在save方法前设置OID是无效的但是也不会报错,在save方…...
DevOps 与持续集成(CI/CD)
1. DevOps 概述 DevOps(Development + Operations)是一种软件开发方法,强调开发(Dev)与运维(Ops)协作,通过自动化工具提高软件交付效率。其目标是: ✅ 提高部署速度 —— 频繁发布新版本 ✅ 减少人为错误 —— 通过自动化降低运维风险 ✅ 增强可观测性 —— 监控和日…...
下一代AI App架构:前端生成,后端消失
过去十年,Web 和 App 的开发范式基本稳定:前端负责交互体验,后端负责业务逻辑和数据管理。即使是“无服务架构”也只是将后端“拆散”而非“消失”。 但随着 AI 原生应用的兴起,特别是 大模型本地化、小模型部署、WebAssembly、L…...
告别过去,奔向未来
人生就是一个不断雕刻自己的过程!一路走来,我们经历过酸甜苦辣咸,迷茫过,跌倒过,懈怠过……但是,我想说这又何妨!一个成功人士的经历必定是跌跌宕宕,起起伏伏的。关键是我们要做到&a…...
AF3 Recycling机制
在 AlphaFold3中,输入数据的特征加工中生成了recycling 维度的数据,主要通过ensembled_transform_fns函数抽样得到不同的扰动的MSA、template特征等,类似于数据增强的作用。在数据集的加载和模型的训练中利用了这一维度的数据,增强了模型的稳定性和鲁棒性,避免单一预测结果…...
notepad++8.6.4安装及细节
notepad8.6.4下载安装(附安装包) 一、安装包下载1.1方法一:官网下载(点击跳转)1.2方法二:网盘链接分享8.6.4版本 二、安装过程细节2.1这里的组件建议全部勾选。点击“下一步”。2.2 勾选①:可以…...
谁该处理我的请假?——责任链模式
谁该处理我的请假?——责任链模式 一、生活中的责任链:请假审批流程二、责任链模式的核心特点三、代码实现:请假审批责任链四、工作中的实际应用场景五、框架中的经典应用六、模式本质理解 一、生活中的责任链:请假审批流程 想象…...
【NLP应用场景全解】自然语言处理如何改变世界?
自然语言处理作为人工智能的重要分支,正在加速改变各行各业。根据Statista预测,到2025年,全球NLP市场规模将达到438亿美元。本文将系统梳理NLP的主要应用场景,结合最新技术趋势,帮助你了解NLP技术的落地现状与未来发展…...
Hive 中书写SQL注意的地方
1.1 关于 DDL (1)创建带有主键约束的 Hive 表时报错。 Hive 目前还没有严格支持“主键约束”,创建带有主键约束的 HIVE 表时报了如下错误: SemanticException [Error 10326]: Invalid Constraint: syntax ENABLE/ENFORCED featu…...
Ubuntu 下 无界面环境 多进程/多线程 使用DrissionPage
使用wget “https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb” -O chrome.deb 安装chrome # !/usr/bin/python3 # -*- coding:utf-8 -*- """ author: JHC000abcgmail.com file: dp.py time: 2025/2/20 20:22 desc:wget "htt…...
Opencv计算机视觉编程攻略-第十节 估算图像之间的投影关系
目录 1. 计算图像对的基础矩阵 2. 用RANSAC 算法匹配图像 3. 计算两幅图像之间的单应矩阵 4. 检测图像中的平面目标 图像通常是由数码相机拍摄的,它通过透镜投射光线成像,是三维场景在二维平面上的投影,这表明场景和它的图像之间以及同一…...
RocketMQ 01
今天是2025/04/06 21:31 day 18 总路线请移步主页Java大纲相关文章 今天进行RocketMQ 1,2 个模块的归纳 首先是RocketMQ 的相关内容概括的思维导图 1. 核心组件 1.1 NameServer 核心功能 服务发现:作为轻量级注册中心,管理所有 Broker 的地址和路由信…...
牛客周赛———字符串
题目如下 思路(贪心) >和<的位置是固定不变的,所以先处理这两个符号,然后再遍历一遍检查‘Z’,如果不符合条件将Z的位置改变正负性使其满足条件,然后遍历的时候记数答案就行了,注意s的首…...
在Hive中,将数据从一个表查询并插入到另一个表
1. 确认目标表结构 确保目标表已存在且结构与查询结果匹配。若不存在,需先创建: CREATE TABLE target_table ( id INT, name STRING ) PARTITIONED BY (dt STRING) STORED AS ORC; 2. 选择插入方式 覆盖插入(替换现有数据࿰…...
优雅实现级联选择器:CascadeSelect 类设计与实现
在现代Web开发中,级联选择器是一种常见的UI组件,它能够有效地组织和展示层级数据。本文将深入解析一个功能完善的级联选择器实现——CascadeSelect类,展示如何用面向对象的方式构建可复用的UI组件。 组件概述 CascadeSelect是一个二级下拉框…...
26考研 | 王道 | 数据结构 | 第五章 树
第五章 树 5.1. 树的概念 5.1.1. 树的基本定义 树:n(n>0)个节点的有限集合,是一种逻辑结构,当n0时为空树,且非空树满足: 有且仅有一个特定的称为根的节点当n>1时,其余结点可分为m (m >0) 个互不相交的有限集合&#x…...
Spring 怎么解决循环依赖问题?
Spring 循环依赖(circular dependency) 指的是多个 Bean 之间的相互依赖,比如: A 依赖 B,B 又依赖 A;或者 A → B → C → A 这种嵌套循环依赖。 这是一个常见又棘手的问题,但 Spring 是可以解…...
微软推出首款量子计算芯片Majorana 1
全球首款拓扑架构量子芯片问世,2025年2月20日,经过近20年研究,微软推出了首款量子计算芯片Majorana 1,其宣传视频如本文末尾所示。 微软表示,开发Majorana 1需要创造一种全新的物质状态,即所谓的“拓扑体”…...
OSI模型中协议数据单元(PDU)
OSI模型中协议数据单元(PDU) 协议数据单元(Protocol Data Unit, PDU)是网络通信中每一层协议处理的数据单位,其内容和格式由特定层的协议定义。PDU在不同OSI层次中有不同的名称和结构,体现了分层模型的核心…...
代码训练营day24 回溯算法
回溯算法part03 93.复原IP地址 题目链接/文章讲解:代码随想录 视频讲解:回溯算法如何分割字符串并判断是合法IP?| LeetCode:93.复原IP地址_哔哩哔哩_bilibili 本题关键在于终止条件 插入3个’.’时判断 ip地址最后一段是否…...
DP Alt Mode 与 DP协议的关系
1. 什么是 “Alt Mode”(替代模式)? Alt Mode(Alternative Mode) 是 USB Type-C 接口 的扩展协议机制,允许通过 物理接口复用(Pin Reuse) 将USB-C接口动态切换为其他协议࿰…...
【欧拉筛】哥德巴赫猜想题解
哥德巴赫猜想题解 题目传送门 1292. 哥德巴赫猜想 一、题目描述 哥德巴赫猜想指出:任意一个大于4的偶数都可以拆成两个奇素数之和。给定多个偶数(6 ≤ n < 10^6),验证它们是否符合这个猜想。对于每个偶数,输出其素数分解中两数差最大的…...
A*算法详解及Python实现
一、什么是A*算法? A*(读作"A-star")算法是一种广泛使用的路径查找和图形遍历算法,它结合了Dijkstra算法的完备性和贪婪最佳优先搜索的高效性。A*算法通过使用启发式函数来估算从当前节点到目标节点的成本,…...
【C++】第九节—string类(中)——详解+代码示例
hello! 云边有个稻草人-CSDN博客 C_云边有个稻草人的博客-CSDN博客 菜鸡进化中。。。 目录 【补充】 二、string类里面的常用接口 1.resize 2.insert 3.assign 4.erase 5.replacefind 6.c_str 7.rfindsubstr 8.find_first_of、find_last_of、find_first…...
vite.config.js常用配置
vite 是一个基于 Vue3 单文件组件的非打包开发服务器,它做到了本地快速开发启动: 快速的冷启动,不需要等待打包操作; 即时的热模块更新,替换性能和模块数量的解耦让更新飞起; 真正的按需编译,不…...
【C++11(下)】—— 我与C++的不解之缘(三十二)
前言 随着 C11 的引入,现代 C 语言在语法层面上变得更加灵活、简洁。其中最受欢迎的新特性之一就是 lambda 表达式(Lambda Expression),它让我们可以在函数内部直接定义匿名函数。配合 std::function 包装器 使用,可以…...
李臻20242817_安全文件传输系统项目报告_第6周
安全文件传输系统项目报告(第 1 周) 1. 代码链接 Gitee 仓库地址:https://gitee.com/li-zhen1215/homework/tree/master/Secure-file 代码结构说明: project-root/├── src/ # 源代码目录│ ├── main.c # 主程序入口│ ├…...
使用SymPy求解矩阵微分方程
引言 在数学、物理、工程等领域,微分方程常常被用来描述系统的变化和动态过程。对于多变量系统或者多方程系统,矩阵微分方程是非常常见的,它可以用来描述如电路、控制系统、振动系统等复杂的动态行为。今天,我们将通过Python 中的 SymPy 库来求解矩阵微分方程,帮助大家轻…...
Flutter之用户输入网络数据缓存
目录: 1、处理用户输入1.1、按钮1.2、文本1.3、富文本1.4、TextField1.5、Form 2、复选框、Switch 和 Radio2.1、复选框2.2、Switch2.3、Radio 3、选择日期或时间4、滑动5、网络和数据6、本地缓存6.1、在本地内存中缓存数据 7、web端和Flutter样式控制对比7.1、文本…...
华为IP(4)
VRRP(虚拟路由冗余协议) 前言: 局域网中的用户终端通常采用配置一个默认网关的形式访问外部网络,如果默认网关设备发生故障,那么所有用户终端访问外部网络的流量将会中断。可以通过部署多个网关的方式来解决单点故障…...
蓝桥杯刷题周计划(第四周)
目录 前言题目一题目代码题解分析 题目二题目代码题解分析 题目三题目代码题解分析 题目四题目代码题解分析 题目五题目代码题解分析 题目六题目代码题解分析 题目七题目代码题解分析 题目八题目代码题解分析 题目九题目代码题解分析 题目十题目代码题解分析题目代码题解分析 题…...
华为网路设备学习-17
目录 一、加密算法 二、验证算法 三、IPsec协议 1.IKE协议(密钥交换协议) ①ISAKMP(Internet Security Association and Key Management Protocol)互联网安全关联和密钥管理协议 ②安全关联(SA) ③…...
【动态规划】深入动态规划 非连续子序列问题
文章目录 前言例题一、最长递增子序列二、摆动序列三、最长递增子序列的个数四、最长数对链五、最长定差子序列六、最长的斐波那契子序列的长度七、最长等差数列八、等差数列划分II - 子序列 结语 前言 什么是动态规划中的非连续子序列问题? 动态规划中的非连续子序…...
灵魂拷问,指针为什么是C语言的灵魂?
目录 | 引 言 | 内存操作 | 构造复杂的数据结构 | 底层硬件交互 | 指针的陷阱 | 文 末 | 引 言 指针是C语言的灵魂! 这句话是不是很耳熟?但为什么这么说,你知道吗? 本篇小文就从内存、数据结构、底层硬件交互这三个维度来…...
Node.js自定义中间件
目录 Node.js 自定义中间件详细介绍 1. 目录结构 2. 什么是自定义中间件? 3. 代码实现 1. 自定义日志中间件(记录请求信息) 2. 自定义身份验证中间件(校验用户权限) 3. 自定义请求时间中间件(记录请…...
Qt 音乐播放器项目
具体代码见:https://gitee.com/Suinnnnnn/MusicPlayer 文章目录 0. 预备1. 界面1.1 各部位长度1.2 ui文件1.3 窗口前置设置1.4 设置QSS 2. 自定义控件2.1 按钮2.2 推荐页面2.3 CommonPage2.4 滑杆 3. 音乐管理4. 歌词界面4.1 ui文件4.2 LrcPage.h文件 5. 音乐播放控…...
初识数据结构——Java集合框架解析:List与ArrayList的完美结合
📚 Java集合框架解析:List与ArrayList的完美结合 🌟 前言:为什么我们需要List和ArrayList? 在日常开发中,我们经常需要处理一组数据。想象一下,如果你要管理一个班级的学生名单,或…...
LightRAG实战:轻松构建知识图谱,破解传统RAG多跳推理难题
作者:后端小肥肠 🍊 有疑问可私信或评论区联系我。 🥑 创作不易未经允许严禁转载。 姊妹篇: 2025防失业预警:不会用DeepSeek-RAG建知识库的人正在被淘汰_deepseek-embedding-CSDN博客 从PDF到精准答案:Coze…...