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.length
  if (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?.assetInfoList
        const 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?.assetInfoList
      tabs.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.length
    if (index >= 10) return
    const newTabName = `表单 ${++index}`
    tabs.value.push({
      label: newTabName,
      name: newTabName,
      insertForm: {}
    })
    activeTab.value = newTabName
  } else if (action === 'remove') {
    const activeName = activeTab.value
    if (tabs.value.length === 1) return
    tabs.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.length
  if (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()
    // 定位到第一个校验失败的tab
    if (!verifyResult) {
      verifyPass.value = false
      activeTab.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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

松树戈

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值