主题使用sass 五部曲
核心
注意
设定公共变量值(globals)
定义私有变量,私有变量的值就是公共变量的名称
定义一个方法循环出来
调用这个方法.放到私有类名或者root下面
流程
创建 html 里面的类名生成
利用 type 生成主色调和色阶色
构建 创建变量的规范
构建 创建变量的方法
把变量名绑定到第二步生成的值
私有变量三部曲
自定义私有变量比如button的私有变量
私有变量的值对应全局变量
定义循环私有变量的方法
在类名里面调用这个方法
创建 html 里面的类名生成
(1) 创建 一个usenamespace文件,用于生成类名
ts
// 这是第一步 为了给html 生成 类名
// 默认的命名空间
export const defaultNamespace = "Y";
/*
* 通过bem的方法生成所有的命名规则
*/
const _bem = (
namespace: string,
block: string,
element?: string,
modifierAttr?: string,
modifierValue?: string,
): string => {
// block
let classname = `${namespace}-${block}`; // 结果Y-Buton
// element
element && (classname += `__${element}`); // 结果Y-Button__icon
// modifier
modifierAttr && (classname += `--${modifierAttr}`); // 结果Y-Button--disabled
// modifierValue
modifierValue && (classname += `_${modifierValue}`); // 结果Y-Button--disabled_disabled
return classname;
};
// 最后 归纳
export const useNamespace = (block: string) => {
// 默认
const namespace = defaultNamespace;
// block
const b = () => _bem(namespace, block);
// element
const e = (element: string | undefined) =>
element ? _bem(namespace, block, element) : "";
// modifier
const m = (
modifierAttr: string | undefined,
modifierValue?: string | undefined,
) =>
modifierAttr ? _bem(namespace, block, "", modifierAttr, modifierValue) : "";
// is
const is = (name: string, state: boolean) => {
return name && state ? `is-${name}` : "";
};
return {
is,
namespace,
b,
e,
m,
};
};(2) 在组件里面使用
vue
<template>
<button
:class="[
ns.b(),
ns.m(props.type),
ns.m('size', props.size),
ns.is('round', props.round),
ns.is('disabled', props.disabled),
ns.is('text', props.text),
ns.is('link', props.link),
ns.is('block', props.block),
ns.is('border', props.border),
ns.is('circle', props.circle),
]"
:disabled="disabled"
>
<i
v-if="props.prefix"
class="iconfont"
:class="[ns.e('icon'), props.prefix]"
></i>
<span>
<slot></slot>
</span>
<!--后缀图标-->
<i
v-if="props.suffix"
class="iconfont"
:class="[ns.e('icon'), props.suffix]"
></i>
</button>
</template>
<script setup lang="ts">
import { onMounted } from "vue";
import { useNamespace } from "../../utils/usenamespace";
const props = defineProps({
type: {
type: String,
default: "",
},
text: {
type: Boolean,
default: false,
},
round: {
type: Boolean,
default: false,
},
disabled: {
type: Boolean,
default: false,
},
link: {
type: Boolean,
default: false,
},
block: {
type: Boolean,
default: false,
},
border: {
type: Boolean,
default: false,
},
size: {
type: String,
default: "", // 小small,中 就不用写 大large
},
circle: {
type: Boolean,
default: false,
},
// loading
loading: {
type: Boolean,
default: false,
},
// 图标前面
prefix: {
type: String,
default: "",
},
// 图标后面
suffix: {
type: String,
default: "",
},
// loading事件 beforeChange 事件和click事件只会执行beforeChange事件
beforeChange: {
type: Function,
default: undefined,
},
});
const ns = useNamespace("button");
onMounted(() => {
console.log("按钮组件挂载");
});
</script>(3) 生成的结果
html
<button class="Y-button Y-button--primary Y-button--size">
<i class="iconfont Y-button__icon icon-LOADING"></i>
<span>测试图标1</span>
<!--后缀图标--><!--v-if-->
</button>利用sass生成主色调和层次色
- vars.scss(定义所有的变量,最后通过$global导出),在通过方法绑定到全局 这个就是全局变量
scss
// 第2步 创建主色调和主色调层次色
@use "sass:map";
@use "sass:math";
@use "sass:color";
// type 分成5种
$types: primary, success, warning, error;
// sizes 有三种 small, default, large
$sizes: small, default, large;
/* 定义主色调 */
// 主色调初始化
$colors: () !default;
// 主色调合并
$colors: map.deep-merge(
(
// 白色
"white": #ffffff,
// 黑色
"black": #000000,
// 主要
"primary": (
"base": #3069ff,
),
// 成功
"success": (
"base": #14cd70,
),
// warning
"warning": (
"base": #ffa81a,
),
// error
"error": (
"base": #ff4a5b,
)
),
$colors
);
// 获取主色调
$color-white: map.get($colors, "white") !default;
$color-black: map.get($colors, "black") !default;
$color-primary: map.get($colors, "primary", "base") !default;
$color-success: map.get($colors, "success", "base") !default;
$color-warning: map.get($colors, "warning", "base") !default;
$color-error: map.get($colors, "error", "base") !default;
/**
* 设置颜色层次比如
* (error:('base': #ff4a5b,"light-9": rgb(255, 236.9, 238.6), "light-8": rgb(255, 218.8, 222.2), ))
* 设置颜色层次
* $type 类型 primary, success, warning, error
* $number 百分比计算器
* $mode 标识
* $mix-color 混合种颜色
* 最后 !global 设为关键色
*/
@mixin set-color-level($type, $number, $mode: "light", $mix-color) {
$colors: map.deep-merge(
(
$type: (
"#{$mode}-#{$number}": color.mix(
$mix-color,
map.get($colors, $type, "base"),
math.percentage(math.div($number, 10))
),
),
),
$colors
) !global;
}
// 开始生成
@each $type in $types {
@for $i from 1 through 9 {
@include set-color-level($type, $i, "light", $color-white);
}
}
/**
* @debug $colors;
* 结果:
* (
// 白色
'white':#ffffff,
// 黑色
'black':#000000,
// 主要
'primary':(
"base": #3069ff,
"light-9": rgb(234.3, 240, 255),
"light-8": rgb(213.6, 225, 255),
"light-7": rgb(192.9, 210, 255),
"light-6": rgb(172.2, 195, 255),
"light-5": rgb(151.5, 180, 255),
"light-4": rgb(130.8, 165, 255),
"light-3": rgb(110.1, 150, 255),
"light-2": rgb(89.4, 135, 255),
"light-1": rgb(68.69999999999999, 120, 255),
),
// 成功
'success':(
"base": #14cd70,
"light-9": rgb(231.5, 250, 240.7),
"light-8": rgb(208, 245, 226.4),
"light-7": rgb(184.5, 240, 212.10000000000002),
"light-6": rgb(161, 235, 197.8),
"light-5": rgb(137.5, 230, 183.5),
"light-4": rgb(114, 225, 169.2),
"light-3": rgb(90.5, 220, 154.89999999999998),
"light-2": rgb(67, 215, 140.60000000000002),
"light-1": rgb(43.49999999999999, 210, 126.29999999999998),
),
// warning
'warning':(
"base": #ffa81a,
"light-9": rgb(255, 246.3, 232.1),
"light-8": rgb(255, 237.6, 209.2),
"light-7": rgb(255, 228.9, 186.3),
"light-6": rgb(255, 220.2, 163.4),
"light-5": rgb(255, 211.5, 140.5),
"light-4": rgb(255, 202.8, 117.6),
"light-3": rgb(255, 194.1, 94.7),
"light-2": rgb(255, 185.4, 71.8),
"light-1": rgb(255, 176.70000000000002, 48.89999999999999),
),
// error
'error':(
'base': #ff4a5b,
"light-9": rgb(255, 236.9, 238.6),
"light-8": rgb(255, 218.8, 222.2),
"light-7": rgb(255, 200.7, 205.8),
"light-6": rgb(255, 182.6, 189.4),
"light-5": rgb(255, 164.5, 173),
"light-4": rgb(255, 146.4, 156.6),
"light-3": rgb(255, 128.3, 140.2),
"light-2": rgb(255, 110.2, 123.8),
"light-1": rgb(255, 92.1, 107.4),
)
*/
/** 边框 */
$border-color: () !default;
$border-color: map.deep-merge(
(
"default": #e2e6f1,
// 边框主色
"disabled": #ebeef5,
// 边框禁用
"hover": #c9cdd9,
// 鼠标悬停
),
$border-color
);
/** 文字颜色 */
$text-color: () !default;
$text-color: map.deep-merge(
(
"primary": #4d5059,
// 文字主色
"secondary": #7c808c,
// 文字辅色
"disabled": #abb1bf,
// 文字禁用
"placeholder": #c9cdd9,
// 文字占位
"light-8": #f5f6fa,
// 文字占位
"light-9": #fafbff,
// 文字占位
),
$text-color
);
/** 颜色 */
$color: () !default;
$color: map.deep-merge(
(
"white": $color-white,
// 白色
"black": $color-black,
// 黑色
"disabled-bg": "#F5F6FA",
),
$color
);
/** 组件尺寸 */
$component-size: () !default;
$component-size: map.deep-merge(
(
"small": 24px,
// 小的
"default": 32px,
// 默认的
"large": 40px,
// 大的
),
$component-size
);
/** 文字尺寸 */
$font-size: () !default;
$font-size: map.deep-merge(
(
"small": 12px,
// 小的
"default": 14px,
// 默认的
"large": 16px,
// 大的
),
$font-size
);
/** 全局配置 */
$global: (
// 边框颜色
"border-color": $border-color,
// 文字颜色
"text-color": $text-color,
// 边框颜色
"component-size": $component-size,
// 文字颜色
"font-size": $font-size,
// 颜色
"color": $color
);创建变量名配置文件
注意
示例:color:#ff4a5b 但是我们必须得把#ff4a5b换成一个变量,这样主题色替换的时候 我们直接改变变量就可以了
- config.scss(生成类名的方式尊重bem规范)
scss
$namespace: "y" !default; // 前缀
$connect: "-" !default; // 块、子级
$element-connect: "__" !default; // 元素
$modifier-connect: "--" !default; // 修改器
$modifier-value-connect: "_" !default; // 修改器的值
$state-prefix: "is-" !default; // 状态前缀,如禁用、圆角、加载等创建生成变量名的方法
- function.scss
scss
@use "config.scss" as *;
/** 组合变量名称 */
@function createVarName($list) {
$name: "--" + $namespace; // --拼接前缀
@each $item in $list {
// each循环
@if $item != "" {
// 判断不为空时执行
$name: $name + "-" + $item; // 开始拼接
}
}
@return $name; // 返回结果
}
/** 获取变量名称 */
@function getVarName($args...) {
@return createVarName(($args));
}
/**
@debug getVarName('color', 'priamry', 'light', 2);
- 结果 --y-color-priamry-light-2
**/把变量名绑定到生成的值
- mixins.scss
scss
// 第五步把变量名和第二步的值对应起来
@use "sass:map";
@use "function" as *;
@use "var.scss" as *;
@use "config.scss" as *;
// 暴露出去的变量
@forward "function";
@forward "var";
// 绑定主色调
@mixin set-color() {
@each $type in $types {
// 定义一个变量
$color: map.get($colors, $type, "base");
// 赋值
#{createVarName(('color', $type))}: #{$color};
}
}
/**
* 结果
* --y-color-primary: #3069ff;
* --y-color-success: #14cd70;
* --y-color-warning: #ffa81a;
* --y-color-error: #ff4a5b;
**/
// 绑定主色调层次色
@mixin set-color-light() {
@each $type in $types {
@for $i from 1 through 9 {
// 定义一个变量
$color: map.get($colors, $type, "light-#{$i}");
// 赋值
#{createVarName(('color', $type,'light' ,$i))}: #{$color};
}
}
}
/**
* 结果
* --y-color-primary-light-1: rgb(68.7, 120, 255);
* --y-color-primary-light-2: rgb(89.4, 135, 255);
* --y-color-primary-light-3: rgb(110.1, 150, 255);
* --y-color-primary-light-4: rgb(130.8, 165, 255);
* --y-color-primary-light-5: rgb(151.5, 180, 255);
* --y-color-primary-light-6: rgb(172.2, 195, 255);
* --y-color-primary-light-7: rgb(192.9, 210, 255);
* --y-color-primary-light-8: rgb(213.6, 225, 255);
* --y-color-primary-light-9: rgb(234.3, 240, 255);
**/
// 绑定全局变量看的是global.scss
// 拿border-color 举例
// $key= border-color
// $data = {default:xxx,disabled:xxxx}
// $type = default或者disabled
// $value = 就是生成的变量 #e2e6f1,
@mixin set-global-var() {
@each $key, $data in $global {
@if $data {
// 判断是否存在数据
@each $type, $value in $data {
#{createVarName(($key, $type))}: #{$value};
}
}
}
}
/** 结果
* --y-border-color-default: #e2e6f1;
* --y-border-color-disabled: #ebeef5;
* --y-border-color-hover: #c9cdd9;
* --y-padding-small: 6px;
* --y-padding-default: 10px;
* --y-padding-large: 10px;
*/
// 设置组件的变量 对应的就是componentVar.scss 文件
@mixin set-component-var($name, $var, $varKey: "default") {
@each $key, $value in $var {
$varName: getVarName($name, $key);
$val: map.get($var, $key, $varKey);
@if ($val) {
#{$varName}: var(#{$val});
}
}
}
:root {
// 绑定主色调
@include set-color();
// 绑定主色调层次色
@include set-color-light();
// 绑定全局变量
@include set-global-var();
}组件里面调用
html
<style scoped lang="scss">
.Y-button {
padding: var(#{--y-padding-large});
}
</style>自定义私有变量(Button)
componentVar.scss
注意
这里就相当于boder-color:("default":--y-border-color-default)
scss
@use "function" as *;
// 按钮组件配置
@function buttonVar($type: "") {
$button: (
// 默认
"border-color": (
"default": getVarName("border-color", "default"),
"type": getVarName("color", $type),
),
"text-color": (
"default": getVarName("text-color", "primary"),
"type": getVarName("color", "white"),
),
"bg-color": (
"default": getVarName("color", "white"),
"type": getVarName("color", $type),
),
"is-link-color": (
"default": getVarName("text-color", "primary"),
"type": getVarName("color", $type),
),
"is-text-color": (
"default": getVarName("text-color", "primary"),
"type": getVarName("color", $type),
),
"is-text-bg-color": (
"default": getVarName("color", "white"),
"type": getVarName("color", "white"),
),
// hover
"hover-text-color": (
"default": getVarName("color", "primary"),
"type": getVarName("color", "white"),
),
"hover-bg-color": (
"default": getVarName("color", "primary", "light-9"),
"type": getVarName("color", $type, "light-3"),
),
"hover-border-color": (
"default": getVarName("color", "primary", "light-7"),
"type": getVarName("color", $type, "light-3"),
),
"hover-is-link-color": (
"default": getVarName("text-color", "secondary"),
"type": getVarName("color", $type, "light-4"),
),
"hover-is-text-color": (
"default": getVarName("text-color", "primary"),
"type": getVarName("color", $type),
),
"hover-is-text-bg-color": (
"default": getVarName("text-color", "light-8"),
"type": getVarName("color", $type, "light-9"),
),
// disabled
"disabled-text-color": (
"default": getVarName("text-color", "disabled"),
"type": getVarName("color", "white"),
),
"disabled-bg-color": (
"default": getVarName("color", "disabled-bg"),
"type": getVarName("color", $type, "light-5"),
),
"disabled-border-color": (
"default": getVarName("border-color", "disabled"),
"type": getVarName("color", $type, "light-5"),
),
"disabled-is-link-color": (
"default": getVarName("text-color", "disabled"),
"type": getVarName("color", $type, "light-5"),
),
"disabled-is-text-color": (
"default": getVarName("text-color", "disabled"),
"type": getVarName("color", $type, "light-5"),
),
"disabled-is-text-bg-color": (
"default": getVarName("color", "white"),
"type": getVarName("color", "white"),
),
"size": (
"default": getVarName("component-size", "default"),
),
"font-size": (
"default": getVarName("font-size", "default"),
)
);
@return $button;
}把值写到全局变量里面
- vars.scss 举个例子
scss
$border-color: () !default;
$border-color: map.deep-merge(
(
"default": #e2e6f1,
// 边框主色
"disabled": #ebeef5,
// 边框禁用
"hover": #c9cdd9,
// 鼠标悬停
),
$border-color
);
/** 全局配置 */
$global: (
// 边框颜色
"border-color": $border-color
);定义循环变量的方法
这布在上面已经写了.这里在复述下
set-global-var() 这里就是把全局变量都循环出来.我放在root下面了
set-component-var() 这里就是组件私有变量循环出来.我后面会放到对应的Y-button里面或者其他的类名
顺序就是 定义全局->绑定全局->定义私有->私有属性的值就是全局变量-> 绑定私有
scss
// 绑定主色调层次色
@mixin set-color-light() {
@each $type in $types {
@for $i from 1 through 9 {
// 定义一个变量
$color: map.get($colors, $type, "light-#{$i}");
// 赋值
#{createVarName(('color', $type,'light' ,$i))}: #{$color};
}
}
}
// 循环全局变量看的是global.scss
// 拿border-color 举例
// $key= border-color
// $data = {default:xxx,disabled:xxxx}
// $type = default或者disabled
// $value = 就是生成的变量 #e2e6f1,
@mixin set-global-var() {
@each $key, $data in $global {
@if $data {
// 判断是否存在数据
@each $type, $value in $data {
#{createVarName(($key, $type))}: #{$value};
}
}
}
}
// 循环私有设置组件的变量 对应的就是componentVar.scss 文件
@mixin set-component-var($name, $var, $varKey: "default") {
@each $key, $value in $var {
$varName: getVarName($name, $key);
$val: map.get($var, $key, $varKey);
@if ($val) {
#{$varName}: var(#{$val});
}
}
}
:root {
// 绑定主色调
@include set-color();
// 绑定主色调层次色
@include set-color-light();
// 绑定全局变量
@include set-global-var();
}私有变量调用
html
<style lang="scss" scoped>
// 调用私有变量
@use "../../styles/componentVar.scss" as *;
// 调用循环私有变量的方法
@use "../../styles/mixins.scss" as *;
// 调用获取类名的方法
@use "../../styles/function.scss" as *;
.Y-button {
// 循环私有变量
@include set-component-var("button", buttonVar());
// 引用变量
border-color: var(#{getVarName("button", "border-color")});
}
/*
.Y-button {
--y-button-border-color: var(--y-border-color-default);
--y-button-text-color: var(--y-text-color-primary);
--y-button-bg-color: var(--y-color-white);
--y-button-is-link-color: var(--y-text-color-primary);
--y-button-is-text-color: var(--y-text-color-primary);
--y-button-is-text-bg-color: var(--y-color-white);
}
*/
</style>