vue中的scoped坑点

今天在覆盖iview组件样式的时候发现一个问题,就是没法覆盖组件原有的样式,最后在github的issue中找到了答案: 不要使用scoped属性。因而我查找了下关于scoped的文章。css

咱们假设把这种组件叫作模块私有组件,其余的未加scoped的叫作模块通常组件。经过查看DOM结构发现:vue经过在DOM结构以及css样式上加惟一不重复的标记,以保证惟一,达到样式私有化模块化的目的。html

代码以下:vue

//valChange.less(使用了嵌套规则)
#valueSlide{
	.bigSlider .ivu-slider-wrap{
		height: 6px;
	}
	.bigSlider .ivu-slider-bar {
		height: 6px;
	}
	.bigSlider .ivu-slider-button{
		width: 14px;
	    height: 14px;
	} 
}

//html部分
<style lang="less" scoped>
	@import "./valChange.less";
</style>
<div class="valid-panel">
	<div class="containerBox">
		<div id="valueSlide" v-bind:style="validStyle">
			<Slider ></Slider>
		</div>
	</div>
</div>
复制代码

也就是咱们在style中使用scoped属性会出现下面的状况: HTML部分: git

HTML部分
CSS部分:
这里写图片描述

从上面的字能够看出,添加了scoped属性的组件,为了达到组件样式模块化,作了两个处理:github

  • 给HTML的DOM节点加一个不重复data属性(形如:data-v-19fca230)来表示他的惟一性
  • 在每句css选择器的末尾(编译后的生成的css语句)加一个当前组件的data属性选择器(如[data-v-2311c06a])来私有化样式

那么问题来了: 对于当前组件下调用的其余组件,data属性只会添加到第一层HTML中: segmentfault

这里写图片描述
对于咱们想覆盖的样式则没法起到做用:(在浏览器调试中手动添加 [data-v-19fca230] 属性后能够匹配)
这里写图片描述

解决方案: 不使用scoped属性,更多详细介绍能够参考这篇文章浏览器

总结一下scoped三条渲染规则:bash

  • 给HTML的DOM节点加一个不重复data属性(形如:data-v-19fca230)来表示他的惟一性
  • 在每句css选择器的末尾(编译后的生成的css语句)加一个当前组件的data属性选择器(如[data-v-19fca230])来私有化样式
  • 若是组件内部包含有其余组件,只会给其余组件的最外层标签加上当前组件的data属性

问题补充: 1.若是不使用scoped如何解决样式全局污染? 推荐使用scoped推进组件私有化,文章所提到的不使用仅出如今已有UI库的样式覆盖上(固然人家用了scoped 那就很难办了)。 首先,解决组件样式全局污染,也就是咱们在这里不使用scoped 覆盖了样式,那么咱们在其余地方调用该组件就会被覆盖。那么咱们在使用组件的时候对组件给一个类名 或者其余甄别属性(id),覆盖样式就针对该类名进行重写样式。 其次,解决其余样式全局污染,若是咱们经过:less

<style lang="less">
    @import "./test.less";
</style>
复制代码

引进样式,那么不使用scoped"./test.less" 中的其余类名样式可能会污染全局,我这里用一个比较笨的方法处理:在模板中使用两次<style></style> 标签:iview

<style lang="less" scoped>
    @import "./test.less";
</style>
<style lang="less">
	//你的覆盖样式
</style>
复制代码

这样既覆盖了样式,其余样式不会被覆盖到全局,效果代码我就补贴上来,感兴趣的同窗能够本身试一试。(注意两个标签的顺序)。

官网 vue-loader 中提到每一个vue模板中能够有多个<style></style>标签,因此上面的写法是没有问题的。