1.问题描述
ElementUI MessageBox自定义弹窗大小不生效:
最近在做vue项目时,碰到一个这样的问题,使用ElementUI中的MessageBox弹窗的时候,由于弹窗提示的内容较多,需要修改ElementUI弹窗里面自带的样式,尝试了以下这几种方法,发现修改后并不生效:
(1)由于这个弹框是在触发按钮时显示的,而不是在页面的结构里,所以无法通过加class属性后,对其进行样式设置,通过查询文档发现,弹框有一个customClass的属性,可以自定义类名,加了类名后对其设置样式依旧不生效
(2)针对第一种情况,仔细想想后,是不是页面结构嵌套比较深,用了样式穿透>>> 和 /deep/ 后发现依旧不生效
最后发现,MessageBox中设置自己想要的样式,样式不可写在带有scoped的style标签里,之后我又加了一个不带有scoped的标签里,发现立刻生效了。
2.解决方案
首先在this.$confirm()中加入customClass属性,由于在开发项目时,一般样式都会放在含有scoped的标签里,所以我们需要单独加一个不含有scoped的标签
this.$confirm('是否要退回?','提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type:'warning',
customClass: 'messageBox'
})
<style>
// 不含scoped的标签样式
.messageBox {
width: 350px;
}
</style>
<style lang="less" scoped>
// 含scoped标签的样式
</style>
3.针对scoped属性的扩展:
针对以上的问题,我又研究了一下style中带有scoped和不带有scoped的区别:
首先,在Vue文件中的style标签上有一个特殊的属性,scoped。当一个style标签拥有scoped属性时候,它的css样式只能用于当前的Vue组件,可以使组件的样式不相互污染。如果一个项目的所有style标签都加上了scoped属性,相当于实现了样式的模块化。
3.1 scoped实现私有化样式的原理
添加了scoped属性的组件,能够使组件样式模块化,它会给HTML的DOM节点加一个不重复data属性(形如:data-v-2311c06a)来表示他的唯一性,在每句css选择器的末尾(编译后生成的css语句,可以在浏览器的元素检查看到)加一个当前组件的data属性选择器(如[data-v-2311c06a])来私有化样式。例子如下:
公共组件button组件
一个公共组件button,为了样式模块化,给其加上scoped属性
//button.vue
<template>
<div class="button-warp">
<button class="button">text</button>
</div>
</template>
...
<style scoped>
.button-warp{
display:inline-block;
}
.button{
padding: 5px 10px;
font-size: 12px;
border-radus: 2px;
}
</style>
浏览器渲染button组件(打开浏览器后台,点击元素检查即可看到)
<div data-v-2311c06a class="button-warp">
<button data-v-2311c06a class="button">text</button>
</div>
.button-warp[data-v-2311c06a]{
display:inline-block;
}
.button[data-v-2311c06a]{
padding: 5px 10px;
font-size: 12px;
border-radus: 2px;
}
3.2 为什么需要穿透scoped?
引用了第三方组件后,需要在组件中局部修改第三方组件的样式,而又不想去除scoped属性造成组件之间的样式污染。此时只能通过特殊的方式,穿透scoped
3.3 样式穿透的方法
样式穿透的写法有三种:>>>、/deep/、::v-deep
注意: 样式穿透的三种方法请详见ElementUI专栏