前言
在使用第三方组件时,有时候组件提供的默认样式不满足我们的实际需求,需要对默认样式进行调整,这就需要用到样式穿透。本篇文章以vue3使用element-ui的Tabs组件,对Tabs组件的添加按钮样式进行客制化为例。
确定需要修改的组件
组件代码
<template>
<el-tabs
v-model="editableTabsValue"
type="card"
class="demo-tabs"
editable
@edit="handleTabsEdit"
>
<template #add-icon>
<el-icon><Select/></el-icon>
</template>
<el-tab-pane
v-for="item in editableTabs"
:key="item.name"
:label="item.title"
:name="item.name"
>
{{ item.content }}
</el-tab-pane>
</el-tabs>
</template>
预览&确认修改目标
例如修改新闻标签下Tabs
组件的添加按钮样式,计划将边框范围扩大、边框调整成圆形、√图标扩大
新建div以及自定义class
新建一个div
,将el-tabs
组件包住,并声明一个语义清晰的自定义class name
,此处以new-tabs
为例
<template>
<div class="new-tabs">
<el-tabs
v-model="editableTabsValue"
type="card"
class="demo-tabs"
editable
@edit="handleTabsEdit"
>
<template #add-icon>
<el-icon><Select/></el-icon>
</template>
<el-tab-pane
v-for="item in editableTabs"
:key="item.name"
:label="item.title"
:name="item.name"
>
{{ item.content }}
</el-tab-pane>
</el-tabs>
</div>
</template>
在浏览器调整样式
定位需要调整的组件
在浏览器打开开发者模式,开启元素检查模式
定位需要调整的添加按钮,关注离选择元素最接近的class
,此处为el-tabs__new-tab
,我们可以在右侧观察到el-tabs__new-tab中需要调整的样式,以及刚才新增的自定义样式new-tabs
在浏览器中调整&预览样式
关注右侧el-tabs__new-tab
的样式,我们需要边框范围扩大、边框调整成圆形、√图标扩大。于是将height
和width
从20px调整为30px,border-radius
调整成15px,font-size
调整成16px
此时,我们只对样式进行了临时修改,刷新页面后会恢复原状,还需要对css代码进行调整,见下文
整理&修改样式穿透css
上文在浏览器中对el-tabs__new-tab
的修改整理如下
.el-tabs__new-tab {
height: 30px;
width: 30px;
border-radius: 15px;
font-size: 16px;
}
在<style scoped>
中申明样式穿透(scoped能够限制自定义样式只会影响当前页面),以我们自定义的classnew-tabs
开头,使用:deep()
(vue3推荐),参数为上文定位的el-tabs__new-tab
<style scoped>
/* 新闻 */
.new-tabs :deep(.el-tabs__new-tab){
height: 30px;
width: 30px;
border-radius: 15px;
font-size: 16px;
}
</style>
确认修改效果
刷新,观察页面渲染,定位到按钮后,观察样式,可知道自定义样式生效,成功覆盖了默认样式
页面完整代码
码云https://gitee.com/pinetree-cpu/hello_vue3
<template>
<div class="new-tabs">
<el-tabs
v-model="editableTabsValue"
type="card"
class="demo-tabs"
editable
@edit="handleTabsEdit"
>
<template #add-icon>
<el-icon><Select/></el-icon>
</template>
<el-tab-pane
v-for="item in editableTabs"
:key="item.name"
:label="item.title"
:name="item.name"
>
{{ item.content }}
</el-tab-pane>
</el-tabs>
</div>
</template>
<script setup lang="ts" name="News">
import axios from "axios";
import { ref } from 'vue'
import { Select } from '@element-plus/icons-vue'
import type { TabPaneName } from 'element-plus'
let tabIndex = 2
const editableTabsValue = ref('2')
const editableTabs = ref([
{
title: 'Tab 1',
name: '1',
content: 'Tab 1 news content',
},
{
title: 'Tab 2',
name: '2',
content: 'Tab 2 news content',
},
])
const handleTabsEdit = (
targetName: TabPaneName | undefined,
action: 'remove' | 'add'
) => {
if (action === 'add') {
const newTabName = `${++tabIndex}`
editableTabs.value.push({
title: 'New Tab',
name: newTabName,
content: 'New Tab content',
})
editableTabsValue.value = newTabName
} else if (action === 'remove') {
const tabs = editableTabs.value
let activeName = editableTabsValue.value
if (activeName === targetName) {
tabs.forEach((tab, index) => {
if (tab.name === targetName) {
const nextTab = tabs[index + 1] || tabs[index - 1]
if (nextTab) {
activeName = nextTab.name
}
}
})
}
editableTabsValue.value = activeName
editableTabs.value = tabs.filter((tab) => tab.name !== targetName)
}
}
</script>
<style scoped>
/* 新闻 */
.new-tabs :deep(.el-tabs__new-tab){
height: 30px;
width: 30px;
border-radius: 15px;
font-size: 16px;
}
</style>