• 技术文章 >web前端 >Vue.js

    Vue3学习之深度剖析CSS Modules和Scope

    青灯夜游青灯夜游2023-01-11 20:34:44转载92

    Css Modules 是通过对标签类名进行加装成一个独一无二的类名,比如.class 转换成.class_abc_123,类似于symbol,独一无二的键名

    Css Scope 是通过为元素增加一个自定义属性,这个属性加上独一无二的编号,而实现作用域隔离。

    原理

    CSS Modules

    CSS Modules实现CSS模块化的原理就是根据我们在config文件中定义的类名命名规则给类生成一个独一无二的命名,从而实现作用域的隔离。【相关推荐:vuejs视频教程web前端开发

    <style module>
      .title {
        font-size: 14px;
        font-family: Microsoft YaHei, Microsoft YaHei-Bold;
        font-weight: 700;
        color: #13161b;
      }
      .name {
        display: flex;
        align-items: center;
        &-img {
          width: 24px;
          height: 24px;
          border-radius: 4px;
        }
        &-text {
          font-size: 14px;
          font-family: Microsoft YaHei, Microsoft YaHei-Regular;
          font-weight: 400;
          color: #13161b;
        }
      }
    </style>
       cell: (h, { col, row }) => {
          // console.log(style);
          return (
            <span class={style.name}>
              <img src={testImage} class={style['name-img']} />
              <span class={style['name-text']}>{row.name}</span>
            </span>
          );
        },

    标签.name-img 被转化成了_name_img_6hlfj_11等

    Scoped CSS

    Vue Loader默认使用CSS后处理器PostCSS来实现Scoped CSS,原理就是给声明了scoped的样式中选择器命中的元素添加一个自定义属性,再通过属性选择器实现作用域隔离样式的效果。

    <template>
      <div class="example">hi</div>
    </template>
    <style module>
    .example {
      color: red;
    }
    </style>
    <!-- 用自定义属性把类名封装起来了 -->
    <style>
    .example[data-v-f3f3eg9] {
      color: red;
    }
    </style>
    <template>
      <div class="example" data-v-f3f3eg9>hi</div>
    </template>

    应用

    CSS Modules

    关于应用,这里只针对介绍Vue3版本内的使用问题

    在 Vue3 中,CSS Modules,在 <style> 上增加 module 属性,即<style module>
    <style module> 代码块会被编译为 CSS Modules 并且将生成的 CSS 类作为 $style 对象的键暴露给组件,可以直接在模板中使用 $style。而对于如 <style module="content"> 具名 CSS Modules,编译后生成的 CSS 类作为 content 对象的键暴露给组件,即module 属性值什么,就暴露什么对象。

    useCssModule模块名使用

    <script setup>
    import { useCssModule } from 'vue'
    
    // 不传递参数,获取<style module>代码块编译后的css类对象
    const style = useCssModule()
    console.log(style.success)  // 获取到的是success类名经过 hash 计算后的类名
        
    // 传递参数content,获取<style module="content">代码块编译后的css类对象
    const contentStyle = useCssModule('content')
    </script>
    
    <template>
      <div>普通style red</div>
    
      <div :class="$style.success">默认CssModule pink</div>
      <div :class="style.success">默认CssModule pink</div>
    
      <div :class="contentStyle.success">具名CssModule blue</div>
      <div :class="content.success">具名CssModule blue</div>
    </template>
    
    <!-- 普通style -->
    <style>
    .success {
      color: red;
    }
    </style>
    
    <!-- 无值的css module -->
    <style module>
    .success {
      color: pink;
    }
    </style>
    
    <!-- 具名的css module -->
    <style module="content">
    .success {
      color: blue;
    }
    </style>

    注意,同名的CSS Module,后面的会覆盖前面的。

    针对module命名区分,主要也是应用在JSX和TSX的组件中居多

    Jsx和Tsx组件内应用

    对于 JSX、TSX 组件,由于其没办法用 scoped style,所以 CSS Modules 是个很好的选择:

    比如在script里面写h函数,直接使用样式变量

       cell: (h, { col, row }) => {
          // console.log(style);
          return (
            <span class={style.name}>
              <img src={testImage} class={style['name-img']} />
              <span class={style['name-text']}>{row.name}</span>
            </span>
          );
        },

    比如render函数

    <script>
    export default {
      props: {
        text: {
          type: String,
          default: ''
        }
      },
      render(h) {
        return <span class={this.$style.span1}>hello 222 - {this.text}</span>;
      }
    };
    </script>
    
    <style module>
    .span1 {
      color: blue;
      font-size: 40px;
    }
    </style>

    :global选择器

    在Scope或者Module中使用global时

    :global()允许括号中声明的选择器命中全局,即其类名不会经过规则封装,因此不受作用域的限制。

    实际项目中,当我们希望修改所使用组件库的默认样式时,在使用CSS Modules方案的情况下,就可以通过:global()来修改其默认样式,但是要注意最好外面有一层类封装,否则可能影响全局样式

    :deep深度作用选择器

    深度作用选择器使得父组件的样式可以渗透到子组件,其原理是使用后代选择器。

    /* 转化前 */
    <style scoped>
    .a :deep(.b) {
      /* ... */
    }
    </style>
    
    /* 转化后 */
    .a[data-v-f3f3eg9] .b {
      /* ... */
    }

    实际项目中,当我们希望修改所使用组件库的默认样式时,在使用Scoped CSS方案的情况下,就可以通过深度作用选择器来修改其默认样式。

    几种深度左右选择器的写法:

    但是在Vue3中,已经作出了改进如下:

    小结

    深度作用选择器deep和声明为global样式的区别,深度作用选择器只是为了能让父组件控制子组件样式,而global样式是全局起效的。

    CSS ModulesScoped CSS
    需要在vue.config.js中额外配置Vue Loader默认支持,无需额外配置
    通过根据配置的类命名规则,为元素生成独一无二的类名来实现作用域隔离通过给元素自定义hash属性,再使用属性选择器选中元素来实现作用域隔离
    在style标签中声明module在style标签中声明scoped
    支持导入其他module的样式,支持样式组合/
    通过:global()来解除作用域的隔离,使样式在全局生效1. 可以定义全局样式,使样式不受作用域约束;2. 可以通过深度作用选择器命中子组件,从而控制子组件的样式

    (学习视频分享:vuejs入门教程编程基础视频

    以上就是Vue3学习之深度剖析CSS Modules和Scope的详细内容,更多请关注php中文网其它相关文章!

    声明:本文转载于:掘金社区,如有侵犯,请联系admin@php.cn删除
    专题推荐:前端 Vue.js
    上一篇:一文详解Vue2/Vue3的响应式原理 下一篇:自己动手写 PHP MVC 框架(40节精讲/巨细/新人进阶必看)

    相关文章推荐

    • 一文详解vue怎么实现v-model(附代码示例)• vue组件怎么传值• 深入聊聊vue3中的reactive()• 详解Vue3响应式的两大利器:ref与reactive• Vue作者尤雨溪发文展望2023,回顾2022!
    1/1

    PHP中文网