vue 组件中使用了 element-plus 组件
vue
<template>
<el-dialog
:model-value="visible"
:title="title"
:width="width + 'px'"
:before-close="onClose"
>
<div class="container" :style="{height:height + 'px'}">
<slot name="content"></slot>
</div>
<template #footer>
<div class="dialog-footer">
<el-button plain type="danger" @click="onClose">取消</el-button>
<el-button plain type="primary" @click="onConfirm">
确定
</el-button>
</div>
</template>
</el-dialog>
</template>
<style lang="scss" scoped>
// 组件内自定义的 elementplus 的样式,
:deep(.el-dialog){
border-radius: 10px!important;
background-color: #535bf2;
}
使用了:deep()失效
bug 剖析
1. 组件的样式与第三方子组件样式的加载顺序
- 若第三方子组件是完全引入的,比如 element-plus:子组件在应用启动的时候,样式就加载了
- 若第三方子组件是按需导入的,那么先加载组件,然后加载子组件。
2. 样式中scoped
当在一个Vue SFC的<style>
标签中添加scoped属性时,Vue编译器会为该组件内的所有元素添加一个唯一的属性(例如data-v-f3f3eg9),同时修改样式规则以匹配这个属性。这意味着这些样式只会应用于当前组件内的元素,而不会影响全局或其他组件中的相同类名或标签。
示例:
vue
<template>
<div class="example">Hello, scoped CSS!</div>
</template>
<style scoped>
.example {
color: red;
}
</style>
编译后可能会变成类似这样:
vue
<template>
<div class="example" data-v-f3f3eg9>Hello, scoped CSS!</div>
</template>
<style>
.example[data-v-f3f3eg9] {
color: red;
}
</style>
3. :deep()失效原因
vue
<template>
<el-dialog
:model-value="visible"
:title="title"
:width="width + 'px'"
:before-close="onClose"
>
<div class="container" :style="{height:height + 'px'}">
<slot name="content"></slot>
</div>
<template #footer>
<div class="dialog-footer">
<el-button plain type="danger" @click="onClose">取消</el-button>
<el-button plain type="primary" @click="onConfirm">
确定
</el-button>
</div>
</template>
</el-dialog>
</template>
<style lang="scss" scoped>
// 组件内自定义的 elementplus 的样式,
:deep(.el-dialog){
border-radius: 10px!important;
background-color: #535bf2;
}
- 子组件是完全引入的,那么先加载子组件,后加载该组件。
- 组件的
<template></template>
中只含有子组件,那么组件的样式会覆盖子组件的样式 - 加载父组件的时候,由于子组件已加载完成,Vue 编译器无法为组件中的元素(即子组件)添加唯一属性,也就无法将组件的样式绑定到子组件。
故,使用:deep()
,样式依然失效。
解决办法
在组件的<template></template>
中,将子组件放入到<div></div>
标签中,那么在加载组件的时候,组件的样式会绑定到<div></div>
标签上。
vue
<template>
<div>
<el-dialog
:model-value="visible"
:title="title"
:width="width + 'px'"
:before-close="onClose"
>
<div class="container" :style="{height:height + 'px'}">
<slot name="content"></slot>
</div>
<template #footer>
<div class="dialog-footer">
<el-button plain type="danger" @click="onClose">取消</el-button>
<el-button plain type="primary" @click="onConfirm">
确定
</el-button>
</div>
</template>
</el-dialog>
</div>
</template>