zoukankan      html  css  js  c++  java
  • vue中的css作用域、vue中的scoped坑点

    一、css作用域

      之前一直很困扰css的作用域问题,即使是模块化编程下,在对应的模块的js中import css进来,这个css仍然是全局的。导致在css中需要加上对应模块的html的id/class 使用css选择器 保证css的作用域不会变成全局 而被其它模块的css污染。

      在vue中引入了scoped这个概念,scoped的设计思想就是让当前组件的样式不会修改到其它地方的样式,使用了data-v-hash的方式来使css有了它对应模块的标识,这样写css的时候不需要加太多额外的选择器,方便很多。

      但是要注意scoped的作用域,因为权重的问题,如果是在子组件使用了scoped,那么在父组件中是不能直接修改子组件的样式的,需要在父组件中使用vue的深度作用选择器。

    .parent >>> .children{ /* ... */ }
    
    .parent /deep/ .children{ /* ... */ }

    二、scoped坑点

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

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

    //valChange.less(使用了嵌套规则)
    #valueSlide{
        .bigSlider .ivu-slider-wrap{
            height: 6px;
        }
        .bigSlider .ivu-slider-bar {
            height: 6px;
        }
        .bigSlider .ivu-slider-button{
             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部分:

      CSS部分:

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

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

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

      对于我们想覆盖的样式则无法起到作用:(在浏览器调试中手动添加 [data-v-19fca230] 属性后可以匹配)

      解决方案:

      不使用scoped属性,更多详细介绍可以参考这篇文章

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

      1、给HTML的DOM节点加一个不重复data属性(形如:data-v-19fca230)来表示他的唯一性

      2、在每句css选择器的末尾(编译后的生成的css语句)加一个当前组件的data属性选择器(如[data-v-19fca230])来私有化样式

      3、如果组件内部包含有其他组件,只会给其他组件的最外层标签加上当前组件的data属性

      问题补充:

      1、如果不使用scoped,如何解决样式全局污染?

      推荐使用scoped推动组件私有化,文章所提到的不使用仅出现在已有UI库的样式覆盖上(当然人家用了scoped 那就很难办了)。

      首先,解决组件样式全局污染,也就是我们在这里不使用scoped 覆盖了样式,那么我们在其他地方调用该组件就会被覆盖。那么我们在使用组件的时候对组件给一个类名 或者其他甄别属性(id),覆盖样式就针对该类名进行重写样式。

      其次,解决其他样式全局污染,如果我们通过:

    <style lang="less">
        @import "./test.less";
    </style>

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

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

      这样既覆盖了样式,其他样式不会被覆盖到全局,感兴趣的同学可以自己试一试。(注意两个标签的顺序)。

      官网 vue-loader 中提到每个vue模板中可以有多个<style></style>标签,所以上面的写法是没有问题的。

  • 相关阅读:
    C语言I博客作业02
    C语言I博客作业06
    C语言I—2019秋作业第一周作业
    C语言I博客作业09
    C语言I博客作业07
    C语言I博客作业08
    利用 jrebel 热部署\远程调试\远程热部署 springboot项目 服务器上的代码
    java 双因素认证(2FA)TOTP demo
    java File读取文件始终不存在的问题分析
    exchange 2010 的两个错误
  • 原文地址:https://www.cnblogs.com/goloving/p/9119460.html
Copyright © 2011-2022 走看看