Vue组件scoped样式中如何让Leaflet divIcon的className样式生效
结论
完全可以将自定义icon的样式统一放在scoped样式块中,不需要单独拆分非scoped的style块。
问题根源
Vue的scoped样式在编译阶段会做两个处理:
- 给当前组件模板内声明的所有原生DOM节点添加唯一的自定义属性标记,格式类似
data-v-xxxxxx - 给scoped块内的所有样式选择器末尾追加对应的属性选择器,比如你写的
.my-custom-icons会被编译为.my-custom-icons[data-v-xxxxxx],保证样式只作用于当前组件内的节点。
而Leaflet的divIcon是通过JS动态创建的DOM节点,会在地图初始化后被插入到地图容器下,Vue编译模板阶段无法感知到这部分动态生成的节点,不会给它们添加对应的scoped属性标记,因此无法匹配到编译后的样式规则。
具体实现方案
方案一:使用深度选择器(推荐)
通过Vue提供的深度作用选择器,可以让指定样式规则不追加scoped属性限制,从而匹配到容器内部动态生成的子节点。
根据你使用的样式类型不同,深度选择器的写法有区别:
- 原生CSS(无预处理器):使用
>>> - Less/Sass/Stylus等预处理器:使用
::v-deep或/deep/
修改后的scoped样式代码示例(原生CSS):
<style scoped> #mapContainer { width: 500px; height: 500px; } /* 深度选择器匹配地图容器下所有自定义icon节点 */ #mapContainer >>> .my-custom-icons { background-color: red; } </style>
如果使用SCSS等预处理器,可以嵌套写法:
<style lang="scss" scoped> #mapContainer { width: 500px; height: 500px; ::v-deep .my-custom-icons { background-color: red; } } </style>
方案二:手动给divIcon节点添加scoped标记
你也可以在组件内获取当前组件的scoped属性ID,手动给divIcon的HTML根节点添加这个属性,让节点能被普通scoped样式匹配到。
组件实例上可以通过this.$options._scopeId拿到当前组件的scoped属性值,创建icon时手动绑定即可:
// 获取当前组件的scoped属性 const scopeAttr = this.$options._scopeId // 如果thecloud是字符串模板,直接把属性拼到根节点上 const thecloud = `<div ${scopeAttr}>自定义icon内容</div>` const cloudIcon = L.divIcon({ html: thecloud, className: 'my-custom-icons', iconSize: [size, size], iconAnchor: [size/2, size/2] })
这种方案下你不需要修改scoped里的样式写法,原本写的.my-custom-icons规则可以直接生效。
内容的提问来源于stack exchange,提问作者ericg
相关产品推荐
相关产品推荐

