常规步骤
1. 创建项目
使用vue cli 脚手架工具创建项目
vue create xxxx
2. 创建全局样式文件
全局样式变量
路径:@/assets/styles/variables.scss
//flex 布局变量
$--flex-direction: ("row", "column");
$--flex-position: ("start", "center", "end");
布局样式类
路径:@/assets/styles/layout.scss
@each $direction in $--flex-direction {
.flex-#{$direction} {
display: flex;
flex-direction: #{$direction};
}
@each $p1 in $--flex-position {
@each $p2 in $--flex-position {
.flex-#{$direction}-#{$p1}-#{$p2} {
display: flex;
flex-direction: #{$direction};
@if $p1!=center {
justify-content: flex-#{$p1};
} @else {
justify-content: #{$p1};
}
@if $p2!=center {
align-items: flex-#{$p2};
} @else {
align-items: #{$p2};
}
}
}
}
}
3. 创建全局公用样式文件
全局共用样式
路径:@/assets/styles/main.scss
@import "@/assets/styles/layout.scss";
div {
@extend .flex-row;
}
4. 引入全局公用样式
在App.vue或者main.js中映入均可
<template>
<router-view />
</template>
<style lang="scss">
@import "@/assets/styles/main.scss";
body {
margin: 0;
padding: 0;
border: none;
outline: none;
}
#app {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
font-family: 微软雅黑;
color: #000000;
}
</style>
5. 配置全局样式类文件
在vue.config.js中配置全局样式类,具体配置方法可以参考vue cli官方文档
const { defineConfig } = require("@vue/cli-service");
module.exports = defineConfig({
transpileDependencies: true,
css: {
loaderOptions: {
scss: {
additionalData: `@import "~@/assets/styles/variables.scss","~@/assets/styles/layout.scss";`
}
}
}
});
FAQ
1. 样式被多次重复编译
原因
-
产生的原因是因为在
vue.config.js
中通过@import
指令导入了SCSS
样式文件`,并且在vue组件库内或者全局样式内再次引入,导致样式类被多次重复编译 -
vue.config.js
是vue编译的入口文件,所以vue在编译时会先加载vue.config.js
内配置的SCSS文件
,而通过@import
指令导入的文件,scss-loader
会在编译后将已经编译的全局样式变量、样式类、带入到后续scss文件
的编译中
解决方法
- 去掉多余的引用文件
例如以下代码,在main.scss中引入了layout.scss文件,而layout.scss文件已经在vue.config.js中配置了载入,所以这里无需再引入
@import "@/assets/styles/layout.scss";
div {
@extend .flex-row;
}
- 使用
@use
指令导入文件,避免文件被多次编译
@use "@/assets/styles/layout.scss" as *;
div {
@extend .flex-row;
}
- 在
vue.config.js
中只配置工具性样式文件
,如果全局变量文件、全局样式类文件;不要引入非工具性样式文件
,例如全局组件样式、main.scss等。所以同理在App.vue文件中只引入非工具性样式文件
,因为如果在App.vue文件中引入工具性样式文件
是不生效的,因为vue项目中,只有在vue.config.js
中配置的样式文件,才会被编译到每个vue组件
样式内
如以下代码,同样会产生多次重复编译
const { defineConfig } = require("@vue/cli-service");
module.exports = defineConfig({
transpileDependencies: true,
css: {
loaderOptions: {
scss: {
additionalData: `@import "~@/assets/styles/main.scss";`
}
}
}
});
2. Undefined variable.
原因
- 原因1:
scss-loader
在编译scss时,是根据从上到下,从前到后的顺序编译,如果文件内的类名不在scss-loader
的堆栈内时,就会抛出以上错误 - 原因2:
@use
导入的文件只对当前文件上下文有效,不会成为全局属性
解决方法
- 原因1:检查引入scss文件的顺序是否正确
例如如下代码:当
variables.scss
文件位于layout.scss
文件后时,在编译layout.scss
时就会抛出变量不存在错误,因为此时scss-loader
的堆栈中没有对应的变量
const { defineConfig } = require("@vue/cli-service");
module.exports = defineConfig({
transpileDependencies: true,
css: {
loaderOptions: {
scss: {
additionalData: `@import "~@/assets/styles/layout.scss","~@/assets/styles/variables.scss";`
}
}
}
});
- 原因2:
- 如果报错位置是在scss文件中:需要检查对应的文件是否被引入,如果没有引入,需要引入对应的文件
- 如果报错位置是在vue组件内,需要查看vue.config.js的配置中是否引入了对应的文件
3. @use rules must be written before any other rules.
原因
- 原因1:
被引用文件
内存在使用@use
指令导入,而引用文件
通过@import
指令导入被引用文件;因为@use
指令不能和其他指令混合 - 原因2:
@use
指令写在了@import
指令后
解决方法
- 问题1:所以在引用文件内使用
@use ‘xxxxx’ as *
作为导入语法
@use '~@/xxx/xxx' as *;
- 问题2:所有的
@use
指令必须放在最前面
@use '~@/xxx/xxx' as *;
@import '~@/xxx/xx';
4. Private members can’t be accessed from outside their modules.
原因
- 问题产生原因是,当使用
@use
导入文件后,因为被应用文件
在声明变量或方法时在方法时,在变量名或方法名前添加了-
或者_
,导致变量或方法成为了当前模块 的私有变量或私有方法 - 通过
@use
方法导入的文件,都会被sass
认为是一个单独的模块,每个模块之间是相互独立的,所以要想使用某个模块属性,就必须是非私有属性,这也就是为什么,@use
可以避免样式被重复编译,因为每个模块只会编译一次
解决方法
- 去掉非私有属性前的
-
和_
5. This variable is available from multiple global modules.
原因
是因为在sass的多个全局模块中,变量名都被定义了一次,比如A模块定义了变量名1,在B模块也定义了变量名1
解决方法
重新命名变量
6. @forward “xxxx/var.scss” with () 重写第三方库后无法直接获取三方库变量
原因
在sass中如果想引用一个变量,需要先导入对应的模块,而@forward
显然不是导入,所以当然不能使用对应的变量
解决方法
- 将需要使用变量的代码写入到新建sass/scss文件中,然后通过
@use
或@import
导入到当前文件中,这样就能解决重写三方库后无法获取变量的问题了