【总结】脚手架项目UI适配、动态换肤、代码规范

【总结】脚手架项目UI适配、动态换肤、代码规范

技术博客 admin 176 浏览

背景

因为最近对UI规范做了改动,所以需要产出一份和UI规范相适配的脚手架,方便各个项目直接接入,脚手架的话并没有从头开始搞,而是在原来的基础上进行改造,把样式进行修改。效果是这样的:

如果说这个样式改动,直接改其实不难,但我们这个代码不期望直接改原来的,希望两种样式都保留下来,所以添加了一个环境变量来区分,两种UI不同的地方的都会通过环境变量为true来做区分。

环境变量定义:

环境变量使用:process.env.VUE_APP_THEME

具体修改主要做了以下几点:

  1. 特有样式覆盖,通过新增一个css文件,将所有复写的样式集中在一起。
  2. 新增了动态换肤的功能
  3. 添加了代码规范和commit规范

样式覆盖

从两边的样式看,最大的不同是:

  1. header
  2. 左侧menu

而改动其实不难,有几个注意点:

  1. 通过样式覆盖把相关的复写样式抽离到一个文件,例如header背景色,color,
  2. 所有涉及到颜色的都改为css变量 var(xxx)的形式,方便切换主题时自动变化。

还有一个是页面表格的样式,之前的搜索列表搜索区域和列表区域是分开的,而新的是一体的,而表格是根据配置项动态生成的,其实是涉及到一个配置项的修改card:true->card:false,为了不一个个改,所以写了个babel插件,编译时动态修改了配置项来实现。具体如下,其实就判断如果是对象,并且key是card且值是true,则将它的值改为false即可。

js
复制代码
module.exports = function () { return { visitor: { ObjectExpression(path) { path.traverse({ ObjectProperty(innerPath) { // console.log('innerPath', innerPath.node) if (innerPath.node.key.name === 'card' && innerPath.node.value.value === true) { // console.log('innerPath inner', innerPath.node) innerPath.node.value.value = false; } } }) } } } }

以上做完后,会根据process.env.VUE_APP_THEME来动态加载css文件,和这个babel插件。

js
复制代码
// 动态加载UI特有的文件 if (process.env.VUE_APP_THEME === 'true') { import('@/utils/loadTheme') .then(() => { console.log('loadZylcTheme'); }); }

动态换肤

就是运行时动态切换主题色,用的代码就是 vue-element-admin 这个项目的theme-picker组件

组件核心就是:监听主题色变化,用算法计算出新的颜色的色阶,然后将原来的css文件中的颜色全部替换为新的颜色的色阶。

调色板和色阶

这里涉及到一个调色板的概念,调色板由一系列具有一定代表性的基本色彩及它们的渐变色组成,基本色彩就是主色,其渐变色由色板生成算法计算得到。色板算法比较简单的一种是antDesign发明的tint/shade色彩系统算法,就是在颜色中加入一定比例的黑色或者白色来生成色阶,这个组件使用的就是这种。

例如elementplus官网的默认的主色的色板,主色下面有六个颜色,用于不同状态的颜色设置。。

看官网的源代码,css里就是将主色和白色混合调出--el-color-primary-light-i, 和黑色混合调出了--el-color-primary-dark-2

js
复制代码
// $colors.primary.light-i // --el-color-primary-light-i // 10% 53a8ff // 20% 66b1ff // 30% 79bbff // 40% 8cc5ff // 50% a0cfff // 60% b3d8ff // 70% c6e2ff // 80% d9ecff // 90% ecf5ff @each $type in $types { @for $i from 1 through 9 { @include set-color-mix-level($type, $i, 'light', $color-white); } } // --el-color-primary-dark-2 @each $type in $types { @include set-color-mix-level($type, 2, 'dark', $color-black); } // https://sass-lang.com/documentation/values/maps#immutability // mix colors with white/black to generate light/dark level @mixin set-color-mix-level( $type, $number, $mode: 'light', $mix-color: $color-white ) { $colors: map.deep-merge( ( $type: ( '#{$mode}-#{$number}': mix( $mix-color, map.get($colors, $type, 'base'), math.percentage(math.div($number, 10)) ), ), ), $colors ) !global; }

这个的具体应用就是对于一个按钮,有几种不同的状态,正常态、按压态、不可点,都是不同的颜色,这样就会直接用上面生成的色阶来设置对应的css。

对应关系如下:

知道了色阶的概念后,就知道切换主题时,会根据这个主色算出这个颜色对应的色阶,然后将原有css文件中,所有对应的颜色改成新的颜色即可。当然这里的前提是你的组件的样式都是用的这些css变量定义的颜色,就像elementui的组件库中组件的color大部分都是用的css变量来做的,就是为了方便主题定制。

动态换肤流程

代码theme-picker组件的具体流程就是以下五个步骤:

  1. 监听主题色变化;
  2. 请求默认组件库样式文件,保存在内存,再次切换可以直接使用内存样式;
  3. 根据新的主题色计算色阶10个;
  4. 将默认的文件的颜色都替换为新的色阶;
  5. 项目中style插入的样式也替换为新的色阶

添加代码规范和提交规范

这一块的话,因为项目本身没有,所以把这些都加上了,几件套:eslint、husky、lint-staged、commitlint,很常见的代码规范化工具。

这个地方遇到的一个坑就是,项目的.git目录和.husky目录不是一个目录,那好,不在一个目录的官网也给出了方案:项目不在 Git 根目录 按照这个确实是可以的。

如果问题到这里就结束了也可以皆大欢喜,但是我需要兼容这两种情况。。

解决.git和.husky不在一个目录

因为要兼容两者在一个目录和不在一个目录,所以就得写脚本兼容。脚本的核心就是判断是否在同一个目录,在的话直接安装,不在的话就需要cd到git的目录先安装钩子。

js
复制代码
/** * 查找.git目录, * 如果在当前目录,则直接执行husky install * 如果不在当前目录,则cd到.git的目录, 执行husky install xxx/.husky 安装钩子 */ const fs = require('fs'); const path = require('path'); const { execSync } = require('child_process'); const GIT_DIR = '.git'; const HUSKY_DIR = '.husky'; const FRONTEND_DIR = path.join('frontend', '.husky'); // 检查目录是否存在 function directoryExists(dir) { return fs.existsSync(dir) && fs.lstatSync(dir).isDirectory(); } function findGitDir() { let currentDir = process.cwd(); while (!directoryExists(path.join(currentDir, GIT_DIR))) { const parentDir = path.dirname(currentDir); if (parentDir === currentDir) { return null; } currentDir = parentDir; } return currentDir; } function main() { const gitDir = findGitDir(); if (!gitDir) { console.log(`cant Found .git directory`); } console.log(`Found .git directory at: ${gitDir}`); const huskyDir = path.join(process.cwd(), HUSKY_DIR); const relativeHuskyDir = path.relative(huskyDir, gitDir); console.log('relativeHuskyDir', relativeHuskyDir); if (relativeHuskyDir === '') { console.log('.git 和 .husky 在同一个目录,执行安装'); execSync('husky install', {stdio: 'inherit'}); } else { process.chdir(path.dirname(relativeHuskyDir)); console.log(`.git 和 .husky 不在同一个目录,切换到git目录执行安装${path.dirname(relativeHuskyDir)}, ${path.dirname(huskyDir)}`); execSync(`husky install ${huskyDir}`, { stdio: 'inherit'}); } } main();

到此,husky的安装就兼容完了,还需要修改的就是pre-commit钩子文件的逻辑,也需要判断,如果git和husky在一个目录,则直接执行lint-staged,如果不在,要先cd到husky的目录,再执行命令,这个就是shell脚本了。

shell
复制代码
#!/usr/bin/env sh . "$(dirname -- "$0")/_/husky.sh" # 脚本执行时目录是git根目录 echo "Current directory: $(pwd)" HUSKY_DIR='.husky'; FRONTEND_HUSKY_DIR='frontend/.husky'; # 查找并切换到.husky目录 change_to_husky_dir() { echo "Current directory: $(pwd)" if [ -d "$HUSKY_DIR" ]; then echo 'Found .husky directory in current directory' elif [ -d "$FRONTEND_HUSKY_DIR" ]; then echo "Found .husky directory in frontend"; cd frontend; else echo '.husky directory not found in current or frontend directory'; exit 1 fi return 0 } if change_to_husky_dir; then echo "Current directory: $(pwd)" npx lint-staged else exit 1 fi

这样,终于兼容完了!!!

至此,脚手架样式相关的改造就改造完成啦~~

其他

终于写了一篇文章,后续会在接着写,趁着活动撸羊毛。后续文章:

  1. 动态换肤方案
  2. 离线部署的问题,主要是内网部署各自包缺少,真是有点崩溃。

gq不说别的,就环境这点有点受不了,因为物理隔离,包缺的太多,外网导入内网麻烦的要死,还有各种形式主义、效率低下的问题,所以才不太喜欢这里,但是相比互联网,确实要轻松一些,毕竟最近迎着太阳下班,这不就是我想要的吗?

或者要不要离开北京,换个轻松点的城市?

把自己的郁闷情绪写一写,果然能发泄下,好点之后就得继续想下一步怎么办了。

先在新部门好好干一段时间,看看是什么样的,然后2条腿走路,加油吧,生活已经这么难了,自己就得想开点,人只有自己能救自己,只有自己能治愈自己。

源文:【总结】脚手架项目UI适配、动态换肤、代码规范

如有侵权请联系站点删除!

Technical cooperation service hotline, welcome to inquire!

0.322186s