vue中css样式管理
1. Vue中scoped属性的渲染规则:给DOM节点添加一个不重复的data属性(比如data-v-7ba5bd90)来表示他的唯一性在每个CSS选择器末尾(编译后生成的CSS)加一个当前组件的data属性选择器(如[data-v-7ba5bd90])来私有化样式。选择器末尾的data属性和其对应的DOM中的data属性相匹配子组件的元素上有一个类已经在这个父组件中定义过了,那么这个父组...
1. Vue中scoped属性的渲染规则:
- 给DOM节点添加一个不重复的data属性(比如data-v-7ba5bd90)来表示他的唯一性
- 在每个CSS选择器末尾(编译后生成的CSS)加一个当前组件的data属性选择器(如[data-v-7ba5bd90])来私有化样式。选择器末尾的data属性和其对应的DOM中的data属性相匹配
- 子组件最外层标签上有一个类已经在这个父组件中定义过了,那么这个父组件的样式就也会应用到子组件上。只不过其权重没有子组件同类名的重。
- 如果组件内部包含有其他组件,只会给其他组件的最外层标签加上当前组件的data属性
- 如果父组件想要改变子组件中某个标签样式可以使用>>>连接符或者/deep/来解决
<!-- Button.vue -->
<template>
<button class="btn">
<span> <slot></slot> </span>
</button>
</template>
<style scoped>
.btn { color: red; }
</style>
<!-- App.vue -->
<template>
<div id="app">
<Button class="btn-lg">click</Button> </div>
</template>
<script>
import Button from "./components/Button";
export default {
name: "App",
components: {
Button
}
};
</script>
<style scoped>
.btn>>> span {
color: green;
font-weight: bold;
border: 1px solid green;
padding: 10px;
}
</style>
- 子组件(‘button class=“btn”’) v-html中内在的标签样式不生效,原理以及解决方案同4、5
其实上述中父组件想要修改子组件的样式,在开发中其实是经常遇到的,就我个人开发项目过程中就会遇到在使用element-ui时,对element-ui封装的组件样式并不是很满意,想要修改,我用到的是个比较笨的方法,
<style lang="scss" type="text/scss" rel="stylesheet/scss" scoped>
//这里可以写该父组件的样式,以及子组件最外层元素样式
</style>
<style lang="scss" type="text/scss" rel="stylesheet/scss">
//这里可以写子组件中的样式,但是一定要父组件的唯一标识,表明这个样式只是在特定父组件下的这个组件内部的样式才有变化
#父组件id{
.子组件样式{
.子组件标题样式
}
}
</style>
但是不论上面的使用>>>连接符或者/deep/来解决,还是我的笨方法其实都破坏了已封装好的组件中的样式,但这也失去了组件封装的效果。再次回到以前CSS中令人头痛的问题:CSS作用域。
2. Vue中使用CSS Modules:
这里只是简单说一下,因为还没有使用过CSS Modules接触scope较多,再者个人觉得CSS Modules的使用太过繁琐,而且scope就够解决Css样式管理了,以上只是个人的一点见解,如果下面有不对的地方请多指教!
1. 基本使用方式
在style标签中添加module属性,表示打开CSS-loader的模块模式
<style module>
.btn {
color: red;
}
</style>
在模板中使用动态类绑定:class,并在类名前面加上’$style.’
<template> <button :class="$style.btn">{{msg}}</button> </template>
效果如下所示::class="$style.btn"会被编译成为.Button_btn_3ykLd这个类名,并且样式的选择器也自动发生了相应的变化。
需要注意的点:
- 如果类名包含中划线,或者类名是驼峰式命名,则使用中括号语法
<h4 :class="$style['header-tit']">类别推荐</h4>
- 也可以使用数组或对象语法
<p :class="{ [$style.red]: isRed }">
Am I red?
</p>
<p :class="[$style.red, $style.bold]">
Red and bold
</p>
- 更复杂的对象语法
<ul
:class="{
[$style.panelBox]:true,
[$style.transitionByPanelBox]:needTransition
}">
</ul>
相当不好用啊,scss不能用,二层嵌套样式也不能选择生效,
<template>
<div class="warp">
<div :class="$style['aa']">
123
<div :class="$style['bb']">
ffff
</div>
</div>
<div :class="$style['bb']">
ddddddd
</div>
</div>
</template>
<script>
</script>
//错误示例
<style module lang="scss">
.aa{
background-color: #00B43C;
.bb{
border: 1px solid #66512C;
}
}
/*.aa*/
</style>
正确示例:
<style module>
.aa{
background-color: #00B43C;
}
.aa .bb{
border: 1px solid #66512C;
}
</style>
2.子组件调用父组件样式
<!-- Button.vue -->
<template> <button :class="[$style.btn, primaryClass]">{{msg}}</button> </template>
<script>
export default {
name: 'Button',
props: {
msg: String,
primaryClass: ''
}
}
</script>
<style module>
.btn {
border: 1px solid #ccc;
border-radius: 3px;
padding: 5px 15px;
background: #fefefe;
margin: 5px;
}
</style>
<!-- App.vue -->
<template>
<div id="app">
<Button msg="Default Button" />
<Button :class="{[$style['btn-lg']]: isLg}" msg="Larger Button" />
<Button :class="{[$style['btn-sm']]: isSm}" msg="Smaller Button" />
<Button msg="Primary Button" :primaryClass="$style['btn-primary']" /> </div>
</template>
<script>
import Button from './components/Button'
export default {
name: 'app',
components: {
Button
},
data() {
return {
isLg: true,
isSm: false
}
}
}
</script>
<style module>
.btn-lg {
padding: 15px 30px;
}
.btn-sm {
padding: 5px;
}
.btn-primary {
background: rgb(54, 152, 244);
border-color: rgb(32, 108, 221);
color: #fff;
}
</style>
效果图如下所示:
(虽然上面的方法可以实现子组件调用父组件的样式,但是我还是想吐槽,子组件的样式不就应该写在子组件的样式里吗?这样写不是扰乱了组件样式封装的原本意图了吗?r如果真的想要修改子组件的样式,就像上诉遇到的vue项目中element-ui封装的组件样式并不是很满意,想要修改也不能往element-ui封装的组件里传入一个props来修改样式吧???)
3.配置
官方配置:
// webpack.config.js
{
module: {
rules: [
// ... 其它规则省略
{
test: /\.css$/,
use: [
'vue-style-loader',
{
loader: 'css-loader',
options: {
// 开启 CSS Modules
modules: true,
// 自定义生成的类名
localIdentName: '[local]_[hash:base64:8]'
}
}
]
}
]
}
}
还有一种方式:在vue.config.js中添加如下配置
css: {
loaderOptions: {
css: {
localIdentName: '[name]__[local]-[hash:base64:5]',
camelCase: true
}
}
}
//localIdentName是格式化类名:name是当前文件名称,local是当前定义的类名名,hash是hash生成的字符串,长度为5
//camelCase:在类名有中横线时,'only'在标签上绑定类名时只支持大驼峰,true:支持大驼峰也支持中括号命名
反正两种方式我都没有成功,求大神指教!出来的样式都是这样
总结:
就目前情况可能更适合用scope来实现css样式的局域化管理。通过项目功能的越来越多,由于前期没有一个很好的css样式规划管理,经常删除没用组件页面时需要调整整个项目样式,这就是因为css样式没有局域化的后果。维护起来找不到导致现在标签样式变化的CSS文件等等,综上以下是开发时要注意的点。
- css一定要有标识:方便样式修改查找。
2. 使用scope区域化Css样式
3. 想要修改子组件封装好的样式,一定要在外层写清楚哪个父组件下的子组件的样式,以免修改全局的样式
<style lang="scss" type="text/scss" rel="stylesheet/scss" scoped>
//这里可以写该父组件的样式,以及子组件最外层元素样式
</style>
<style lang="scss" type="text/scss" rel="stylesheet/scss">
//这里可以写子组件中的样式,但是一定要父组件的唯一标识,表明这个样式只是在特定父组件下的这个组件内部的样式才有变化
#父组件id{
.子组件样式{
.子组件标题样式
}
}
</style>
更多推荐
所有评论(0)