vue学习笔记---Scoped CSS和CSS Modules基本使用及比较

Scoped CSS和CSS Modules都是对vue单文件组件中的style标签的一种修饰,使我们能更好地处理不同情况下的样式使用

Scoped CSS


使用

Scoped CSS的使用只需要在style标签上添加scoped即可

<template>
	<div class="example">hello world</div>
</template>
<style scoped>
.example{
	color:#f00;
}
</style>

使用scoped的style,编译后其内的选择器会在其后添加自定义属性data-v-[str],str为一串字符串,而使用该选择器的标签也会写上该自定义属性,而且只会修改当前组件中使用该选择器的标签,所以该选择器也就只能作用于当前组件
上面的代码会编译为:

<template>
	<div class="example" data-v-f3f3eg9>hello world</div>
</template>
<style scoped>
.example[data-v-f3f3eg9]{
	color:#f00;
}
</style>

混用本地和全局样式

我们称使用scoped的style为本地样式,而不使用scoped的style为全局样式,本地样式只能应用于本组件,而全局样式能应用于当前页面的所有组件
因为在vue单文件组件中,可以有多个style,所以我们可以混用本地样式和全局样式

<style>
	/*全局样式*/
</style>
<style scoped>
	/*本地样式*/
</style>

深度作用选择器

如果我们要让scoped组件中的部分选择器能应用到子组件,我们可以通过写一个新的全局样式来将其深入到子组件中,此外,也可以通过深度作用选择器>>>来作用到子组件中

<style scoped>
	.a >>> .b { /* ... */ }
</style>

上面的代码会编译成

<style scoped>
	.a[data-v-f3f3eg9] .b { /* ... */ }
</style>

可以看到,自定义属性被定义在了>>>的位置,所以.b选择器的样式可以作用到子组件中
此外,像Sass,less等一些预处理器无法正确处理深度作用选择器>>>,可以使用/deep/或者::v-deep来代替。

<style lang="less" scoped>
	.a ::v-deep .b{ /* ... */ }
</style>

特殊情况

子组件的根元素

子组件的根元素同时处在当前组件及其子组件中,所以scoped中的样式会对当前子组件的根元素起作用,而子组件中的样式也会对其起作用

<!-- 当前组件 -->
<template>
	<div class="example">
		<child></child>
	</div>
</template>
<style scoped>
	.childExample{
		color:#f00;
	}
</style>
<script>
	import child from './child.vue'
	export default {
		data(){
			return{}
		},
		components:{
			child
		}
	}
</script>
<!-- 子组件 -->
<template>
	<div class="childExample">hello world</div>
</template>
<style scoped>
.childExample{
	font-size:20px;
}
</style>

这里的color和font-size样式都会应用在hello world上

动态生成的内容

通过v-html生成的DOM内容不受scoped样式影响,即使是在同一组件内,因为不会在其标签上添加自定义属性,如果要作用在v-html生成的内容上,可以使用深度选择器来应用在其上

<template>
  <div id="app">
      <span class="example">1</span>
      <div v-html="msg"></div>
  </div>
</template>
<script>
  data(){
    return{
      msg:"<span class='example'>123</span>"
    }
  }
</script>
<style scoped>
  .example{
    color:#f00;
  }
</style>

上面的代码编译后会变为

<div data-v-7ba5bd90="" id="app">
	<span data-v-7ba5bd90="" class="example">1</span>
	<div data-v-7ba5bd90="">
		<span class="example">123</span>
	</div>
</div>

可以看到v-html生成的span标签上没有自定义属性,所以scoped上的样式不会对其起作用。

CSS Modules


使用

CSS Modules是一个用于模块化和组合CSS的系统,在vue-cli搭建的项目中可以直接使用,在webpack中可通过给css-loader传入modules:true来启用

// webpack.config.js
{
  module: {
    rules: [
      // ... 其它规则省略
      {
        test: /\.css$/,
        use: [
          'vue-style-loader',
          {
            loader: 'css-loader',
            options: {
              // 开启 CSS Modules
              modules: true,
              // 自定义生成的类名
              localIdentName: '[local]_[hash:base64:8]'
            }
          }
        ]
      }
    ]
  }
}

在style标签上加上module,就使用了CSS Module了

<style module>
  .example{
    color:#f00;
  }
</style>

上面的代码会编译为

.App_example_1GtWg {
    color: #f00;
}

CSS Module应用的style标签上的样式,会被写在名为$style的计算属性上,在template中可以通过:class来应用该计算属性

<template>
  <div id="app">
      <span :class="$style.example">1</span>
  </div>
</template>

上面的代码会编译为

<div id="app">
	<span class="App_example_1GtWg">1</span>
</div>

JavaScript中访问样式

因为CSS Modules中的样式写在计算属性$style中,所以可以在JavaScript中访问到

<script>
export default {
  data(){
    return{}
  },
  created () {
    console.log(this.$style.example)
  }
}
</script>

这样会打印出编译后的样式名
在这里插入图片描述

子组件中使用

直接写上class名

直接打开页面后使用f12查看,然后直接写上编译后的类名

<!-- 子组件中 -->
<span class="App_example_1GtWg">22</span>

使用props传递

在父组件中,将$style传递到子组件中,子组件就能直接调用里面的字符串

<!-- 当前组件 -->
<template>
  <div id="app">
      <Child :parentStyle="$style"></Child>
      <span :class="$style.example">1</span>
  </div>
</template>
<script>
import Count from './count.vue'
export default {
  data(){
    return{}
  },
  components: {
    Child
  }
}
</script>
<style module>
  .example{
    color:#f00;
  }
</style>
<!-- 子组件 -->
<template>
    <div>
        <span :class="parentStyle.example">22</span>
    </div>
</template>

<script>
export default {
    props:["parentStyle"]
}
</script>

这样子子组件中也能使用父组件中的CSS Modules的样式

自定义名称注入

CSS Modules允许我们自定义生成的计算属性的名称,直接在style标签上写即可

<template>
  <div id="app">
      <span :class="a.example">1</span>
  </div>
</template>

<script>
export default {
  data(){
    return{
    }
  }
}
</script>

<style module="a">
  .example{
    color:#f00;
  }
</style>

注意点

自定义名称的使用

在同一组件内,我们可以为不同的style标签设置不同的自定义CSS Modules名称

<style module="a">
  .example1{
    color:#f00;
  }
</style>
<style module="b">
  .example2{
    color:#0f0;
  }
</style>

但是要注意的是,在同一组件内,不同的module名称对同一选择器名编译生成的名字相同
如下面的代码

<style module="a">
  .example{
    color:#f00;
  }
</style>
<style module="b">
  .example{
    color:#0f0;
  }
</style>

编译后查看控制台
在这里插入图片描述
发现使用了相同的选择器名,所以即使在使用不同Modules名称的style标签中,样式对于当前组件来说是一样的,后写的样式会覆盖先写的样式,当然也正因这样我们可以通过调用不同的module来达到切换样式的效果。

Scoped CSS和CSS Modules的比较


相同点

  • 两者都可以达到将样式只应用在当前组件,而不会影响到其他组件的效果,Scoped CSS是通过使用自定义属性,而CSS Modules是通过修改选择器名
  • 两者都有办法将样式传递到子组件中,Scoped CSS是通过使用深度选择器,而CSS Modules是通过传递选择器名
  • 在同一组件中使用多个style标签时,后面使用的style标签的样式会覆盖前面style标签的样式,即使CSS Modules中设置了不同的自定义名
  • 两者在使用vue cli搭建的项目中都是开箱即可用

不同点

  • 如上面所说的,达到只应用于当前组件和传递到子组件的方式不同
  • CSS Modules可以通过JavaScript得到修改后的类名,而Scoped CSS不行
  • CSS Modules在自己配置时需要将css-loader中的modules设置为true
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值