Skip to content

Vue3 实战 - 配置 scss

安装 sass

bash
$ pnpm install sass -D

在 style 标签中注明即可

vue
<style scoped lang="scss"></style>

什么是 scoped

实现组件的私有化。当前 style 属性只属于当前模块。

DOM 结构中可以发现,vue 通过在 DOM 结构以及 css 样式上加了唯一标记,达到样式私有化,不污染全局的作用。

BEM 架构

他是一种 css 架构 oocss 实现的一种 (面向对象css),BEM 实际上是 blockelementmodifier 的缩写,分别为块层、元素层、修饰符层,element UI 也使用的是这种架构

BEM 命名约定的模式是:

scss
.block {}
 
.block__element {}
 
.block--modifier {}
scss
.el-input__inner    # be
.el-button--success  # bm

使用 sass 最小单元复刻一个 bem 架构,在 src 目录下新建 styles 目录,添加 bem.scss 文件,内容如下:

scss
// bem.scss
$block-sel: "-" !default;
$element-sel: "__" !default;
$modifier-sel: "--" !default;
$namespace:'am' !default;
@mixin bfc {
    height: 100%;
    overflow: hidden;
}
 
// 混入
@mixin b($block) {
   $B: $namespace + $block-sel + $block; //变量
   .#{$B}{ //插值语法#{}
     @content; //内容替换
   }
}
 
@mixin e($element) {
    $selector:&;
    @at-root {
        #{$selector + $element-sel + $element} {
            @content;
        }
    }
}
 
@mixin m($modifier) {
    $selector:&;
    @at-root {
        #{$selector + $modifier-sel + $modifier} {
            @content;
        }
    }
}

全局扩充 scss

ts
# vite.config.ts
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
 
// https://vitejs.dev/config/
export default defineConfig({
    plugins: [vue()],
    css: {
        preprocessorOptions: {
            scss: {
                additionalData: "@import './src/bem.scss';"
            }
        }
    }
})

Vue 组件中使用:

vue
<template>
    <div class="am-wraps">
         <div>
            <Menu></Menu>
         </div>
         <div class="am-wraps__right">
            <Header></Header>
            <Content></Content>
         </div>
    </div>
</template>
 
<script lang="ts" setup>
import { ref, reactive } from "vue"
import Menu from './Menu/index.vue'
import Content from './Content/index.vue'
import Header from './Header/index.vue'
</script>
 
<style lang="scss" scoped>
@include b('wraps'){
    @include bfc;
    @include flex;
    @include e(right){
        flex:1;
        display: flex;
        flex-direction: column;
    }
}
</style>

其他全局样式设置

除了上面配置的 bem.scss 外,我们还有一些其他的需要全局配置的样式(如清除默认样式等),可以如下操作,在 src/styles 目录下新建 index.scss reset.scss custom.scss 文件,内容分别如下:

scss
// index.scss
@import './reset.scss';
@import './custom.scss';
scss
// reset.scss
*,
::before,
::after {
    box-sizing: border-box;
    border-color: currentcolor;
    border-style: solid;
    border-width: 0;
}
#app {
    width: 100%;
    height: 100%;
}
html {
    box-sizing: border-box;
    width: 100%;
    height: 100%;
    line-height: 1.5;
    tab-size: 4;
    text-size-adjust: 100%;
}
body {
    width: 100%;
    height: 100%;
    margin: 0;
    font-family: 'Helvetica Neue', Helvetica, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', '微软雅黑', Arial,
        sans-serif;
    line-height: inherit;
    -moz-osx-font-smoothing: grayscale;
    -webkit-font-smoothing: antialiased;
    text-rendering: optimizelegibility;
}
a {
    color: inherit;
    text-decoration: inherit;
}
img,
svg {
    display: inline-block;
}
svg {
    vertical-align: -0.15em; // 因icon大小被设置为和字体大小一致,而span等标签的下边缘会和字体的基线对齐,故需设置一个往下的偏移比例,来纠正视觉上的未对齐效果
}
ul,
li {
    padding: 0;
    margin: 0;
    list-style: none;
}
*,
*::before,
*::after {
    box-sizing: inherit;
}
a,
a:focus,
a:hover {
    color: inherit;
    text-decoration: none;
    cursor: pointer;
}
a:focus,
a:active,
div:focus {
    outline: none;
}
scss
// custom.scss
// 其他全局样式

main.ts 中引入 index.scss

ts
import '@/styles/index.scss'
import 'virtual:svg-icons-register'
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'

const app = createApp(App)

app.use(router).mount('#app')