上班使用less/sass写项目出现样式冲突怎么办
前几天一个月薪35k的兄弟,给我推了一个人工智能学习网站,看了一段时间挺有意思的。包括语音识别、机器翻译等从基础到实战都有,很详细,分享给大家。
大家都知道css是用来丰富html样式的,less/sass是一种css预处理语言,它们不仅保持了css完整的特性,还对css进行了扩充,例如增加了变量、混合等功能,让css更容易维护。
所以,上班大家必须掌握一种预处理语言。当然less和sass写起来是差不多的,学会一个另一个自然就会了。
简单目标:
- 会通过less/sass来嵌套书写css样式
- 了解 scoped ,加和不加的区别,并且学会使用
- deep深度选择器,学会使用
- 修改第三方组件库样式不起作用怎么办
- 上班使用less/sass出现样式冲突怎么办
- 上班使用less/sass如何避免样式冲突的出现
学习
vue 使用vue-cli创建一个使用less的项目,举个例子,这就是你上班的一个项目。
less/sass的简单使用
css与less/sass简单区别
html
<div class="home">
<h1>css与less/sass简单区别</h1>
</div>
css
.home {
background: #bbb;
}
h1 {
color: red;
}
less/sass
// 加scoped
<style lang="less" scoped>
.home {
background: #bbb;
h1 {
color: red;
}
}
</style>
// 不加scoped
<style lang="less">
.home {
background: #bbb;
h1 {
color: red;
}
}
</style>
结论:通过上面代码,大家可以看出来。css不可以通过父子类名嵌套来写,但是less/sass却可以。
less/sass还有变量、混合等新增特性,我们这里不做赘述,上班这些不会也不影响。但是嵌套必须得会。
less/sass来写样式,是不是必须嵌套来写呢,像css那样,不嵌套来写行不行,答案是可以的,less/sass具备css所有的特性。
在含有scoped的样式标签里写样式
home.vue 你的页面
<template>
<div class="home">
<h1>This is an home page, 我写的页面</h1>
</div>
</template>
<style lang="less" scoped>
.home {
background: #bbb;
h1 {
color: red;
}
}
</style>
about.vue 你同事写的页面
<template>
<div class="about">
<h1>This is an about page, 同事写的页面</h1>
</div>
</template>
结论:同事的文件和你的文件都含有h1标签,你在含有scoped的样式标签里给h1添加红色字体样式,不会影响你同事的文件h1的字体颜色。
在不含有scoped的样式标签里写样式
- 将h1写在文件父元素内,则不会对同事文件有影响
home.vue
<template>
<div class="home">
<h1>This is an home page, 我写的页面</h1>
</div>
</template>
<style lang="less">
.home {
background: #bbb;
h1 {
color: red;
}
}
</style>
- 将h1不写在文件父元素内,单独写在无scoped的样式标签里则会对同事文件有影响
<template>
<div class="home">
<h1>This is an home page, 我写的页面</h1>
</div>
</template>
<style lang="less">
h1 {
color: red;
}
</style>
结论:通过上面代码对比,可以看出来。在无scoped的样式标签里,如果有自己的父类约束,也就是嵌套,则不会对同事的代码造成影响。如果没有约束,就会对同事的代码造成影响,这就是所谓的样式冲突。
这只是两个简单的文件,上班项目文件特别多,几百个文件。如果在不加scoped的标签里写样式,就会影响所有页面的样式,造成样式冲突。
deep深度选择器
在vue中,我们为了避免父组件的样式影响到子组件的样式,会在style中加
但是这样存在着一个问题,比如你使用了别人的组件或者自己开发一个组件,有时候你修改一处就可能影响到别的地方,所以就需要有一个方法或者方式,既不影响到别的地方,又能修改子组件在当前的样式,可以使用 /deep/ 深度选择器。
- 不使用/deep/
home.vue 父组件
<template>
<div class="home">
<h1>This is an home page, 我写的页面</h1>
<hr/>
<h2>下面是子组件内容</h2>
<child-com></child-com>
</div>
</template>
<script>
import childCom from './childCom.vue'
export default {
components: {
childCom
},
}
</script>
<style lang="less" scoped>
.home {
background-color: #fff;
h1 {
color: red;
}
}
</style>
childCom.vue 子组件
<template>
<div class="child">
<h1>This is an about page, 我是子组件</h1>
</div>
</template>
结论:父组件不使用/deep/,给h1设置color,可以看到下面子组件的h1不受影响,依旧为黑色。
- 使用/deep/
home.vue 父组件
<template>
<div class="home">
<h1>This is an home page, 我写的页面</h1>
<hr/>
<h2>下面是子组件内容</h2>
<child-com></child-com>
</div>
</template>
<script>
import childCom from './childCom.vue'
export default {
components: {
childCom
},
}
</script>
<style lang="less" scoped>
.home {
background-color: #fff;
/deep/h1 {
color: red;
}
}
</style>
结论:大家可以看到,在父组件使用了/deep/,子组件的h1也受到了影响,变成了红色,这就是deep的一个使用。
修改第三方组件库的组件样式不起作用怎么办
- 给这个组件的类名前添加/deep/
- 如果添加deep不起作用,就需要在浏览器查看一下dom结构
- 发现这个组件类名不在该页面根标签下,加上根标签类名嵌套就不会起作用,不加就会影响全局,怎么搞?
案例
- 需求:
1、在home的子组件childCom里使用下拉框
2、在about同事写的文件里也使用下拉框
3、只修改同事文件的下拉框option背景颜色,且不影响全局
home.vue
<template>
<div class="home">
<h1>This is an home page, 我写的页面</h1>
<hr/>
<h2>下面是子组件内容</h2>
<child-com></child-com>
</div>
</template>
<script>
import childCom from './childCom.vue'
export default {
components: {
childCom
},
}
</script>
<style lang="less" scoped>
.home {
background-color: #fff;
/deep/h1 {
color: red;
}
}
</style>
childCom.vue
<template>
<div class="child">
<h1>This is an about page, 我是子组件</h1>
<el-select v-model="value" placeholder="请选择">
<el-option
v-for="item in options"
:key="item.value"
:label="item.label"
:value="item.value">
</el-option>
</el-select>
</div>
</template>
<script>
export default {
data() {
return {
options: [{
value: '选项1',
label: '公众号:IT程序员老王'
}, {
value: '选项2',
label: '公众号:IT程序员老王'
}, {
value: '选项3',
label: '公众号:IT程序员老王'
}, {
value: '选项4',
label: '公众号:IT程序员老王'
}, {
value: '选项5',
label: '公众号:IT程序员老王'
}],
value: ''
}
}
}
</script>
about.vue
<template>
<div class="about">
<h1>This is an about page, 同事写的页面</h1>
<el-select v-model="value" placeholder="请选择">
<el-option
v-for="item in options"
:key="item.value"
:label="item.label"
:value="item.value">
</el-option>
</el-select>
</div>
</template>
<script>
export default {
data() {
return {
options: [{
value: '选项1',
label: '公众号:IT程序员老王'
}, {
value: '选项2',
label: '公众号:IT程序员老王'
}, {
value: '选项3',
label: '公众号:IT程序员老王'
}, {
value: '选项4',
label: '公众号:IT程序员老王'
}, {
value: '选项5',
label: '公众号:IT程序员老王'
}],
value: ''
}
}
}
</script>
<style lang="less" scoped>
// /deep/.el-scrollbar {
// background-color: red;
// }
</style>
<style lang="less">
// .about {
// .el-scrollbar {
// background-color: red;
// }
// }
.el-scrollbar {
background-color: red;
}
</style>
在about试了好几次,在scoped里,不管加不加/deep/都不管用
在没有scoped的样式标签里测试,如果在父类名里嵌套写就不起作用。不在父类名里写,直接单独写,有作用了,但是影响全局了。不仅同事的下拉框变成了红色背景,你的也变成了红色背景。
这样肯定是不行的
那么为什么在没有scoped的样式标签里嵌套写就不行呢,看一下浏览器
这个时候你就会发现,组件不在about标签里,那不是人家的孩子,当然不起作用了。
- 解决
查看组件库官方文档,为about的下拉框单独添加一个独有的类名是不是就不会影响全局了?
是不是完美解决了?
关于样式冲突的解决避免
- 一个文件写两个样式标签,一个加scoped,一个不加
- 在加scoped里写本文件样式,子组件样式加/deep/
- 在不加scoped里本文件样式,必须嵌套在父类下
- 在不加scoped里本文件样式,不嵌套在父类下,就会造成样式冲突
- 组件库有的组件可以添加自定义类名