Vue中scoped與CSSModules的用法

qingtonghub發表於2018-11-16

眾所周知,vue中有兩種css渲染模式,一是直接在style中直接加上scoped,另一種是配置CSSModules.

  1. scoped是為了防止各個元件間的class汙染,從而渲染成隔離模式如:
<template>    
<div>        
<div class="box">box</div>    
</div>
</template>

<script>    
export default {}
</script>

<style scoped>    
.box{        
    color: #ccc;    
}
</style>複製程式碼

html渲染成

<div data-v-fae5bece class="box">box</div>複製程式碼

css渲染成

.box[data-v-fae5bece] {
    color: #ccc;
}複製程式碼

現在有一個子元件Comp.vue

<template>    
    <div class="inner">inner-box</div>
</template>
<style scoped>    
.inner {        
    color: #f00;    
}
</style>複製程式碼

父元件對其不加任何修飾,那顯而易見Comp渲染出來的color是 紅色(#f00),現在我希望通過父元件修改Comp中的顏色,通常做法是在父元件的style中加上

<style scoped>    
.box {        
    color: #ccc;    
}    
.box .inner{        
    color: #ccc;    
}
</style>

//或者官方推薦的深度作用選擇器效果一樣.box >>> .inner{    color: #ccc;}複製程式碼

當然顯示出來Comp的顏色已經變成了灰色(#ccc),但是有一點很重要,在HTML中渲染出來的效果是這樣:

<div data-v-9b5d8882 data-v-fae5bece class="inner">
    inner-box
</div>
複製程式碼

.box[data-v-fae5bece] .inner {
    color: #ccc;
}複製程式碼

div中的權重越來越多,inner樣式也失去了封裝的效果,子元件中所有的inner樣式都會被渲染成父元件的樣式,如果有更多的父元件對其修改樣式呢?

2.CSSModules出場了(以下皆為vue2.X)

參看官方vue-loader配置說明:vue-loader.vuejs.org/zh/guide/cs…

配置方式:

  • build/utils.js中找到css-loader,在其options中加上,注:加上後要重啟dev生效

Vue中scoped與CSSModules的用法

直接在vue中的style加上module,class以$style.box的形式訪問,甚至可以通過javascript訪問this.$style.box

<div>
<div :class="$style.box">           <p>box</p>   
</div>
</div>
</template>
<style module>    
.box {        
    color: #ccc;    
}
</style>複製程式碼

也支援以下形式

<p :class="{ [$style.red]: isRed }">
   Am I red?
</p>
<p :class="[$style.red, $style.bold]">
   Red and bold
</p>複製程式碼

如果class是下劃線的形式則需要以下形式訪問

:class="$style['box-a']"複製程式碼

直接看渲染效果

<div class="ms3sHUJ9cRha8f_qHKpJE_0"><p>box</p></div>
複製程式碼

.ms3sHUJ9cRha8f_qHKpJE_0{
    color: #ccc;
}複製程式碼

媽媽再也不用擔心我的樣式汙染啦!

如果現在assets檔案中有一個common.css,然後在template中直接使用common的.red class,然後發現樣式不生效,f12一看原來common中的樣式也被模組化了

.red_1R_DKSL1 {
  color: #f00; 
}
複製程式碼

(注意:commom中的element選擇器並不會被模組化,可以放心使用)

那麼怎麼引用common中的style呢?

引用的方式有很多種看自己喜歡挑選

<script>    
    export default {        
        data: function(){            
            return {                
                style: require('@/assets/sass/common.scss')            
            }        
        }    
    }
</script>複製程式碼

使用方式大致和module一樣

:class="style.box" 
:class="style['aa-bb']"複製程式碼

也可以:

<script>    
    import style from '@/assets/sass/common.scss'    
    export default {        
        data: function(){            
            return {}        
        },        
        created: function(){            
            this.style = style        
        }    
    }
</script>
複製程式碼

也可以:

<script>    
    import style from '@/assets/sass/common.scss'    
    export default {        
        data: function(){            
            return {}        
        },        
        computed: {           
            style : function(){               
                return style           
            },        
        },    
    }
</script>
複製程式碼

任君挑選...

當然如果你不想這麼麻煩,也可以換一種配置

在build/vue-loader.conf.js檔案中

Vue中scoped與CSSModules的用法

然後app.vue中全域性引用

<style lang="scss" src="@/assets/sass/common.scss"></style>複製程式碼

<template>    
    <div>        
        <div :class="$style.box">            
            <p class="red">box</p>        
        </div>    
    </div>
</template>複製程式碼

直接引用common中的red樣式

Vue中scoped與CSSModules的用法

html中渲染出來 是不是很開心~


相關文章