痛点问题描述
我们的业务里,有深色模式和浅色模式的皮肤,我们实现的方案是这样的:

显然,我们会避免在业务代码里写色值的css,我们会事先把所有的颜色统一放到一个公共的CSS文件里,然后每个项目都去引用这个CSS。 因此对于开发者而言,关心的东西不是色值本身,而是色值对应的类名。
所以痛点问题就在于:我们在写样式的时候,先看到蓝湖上的色值,再去根据这个色值搜索对应的类名,然后再复制这个类名,写到HTML代码中。
作为一名Ctrl ACV工程师,我需要思考如何直接快速地通过色值直接取到类名,而不用去代码里搜。
基本思路
我们可以注入一段JS代码,改写色值的点击事件,然后直接自动复制类名。
技术选型
能做到这一点的,就是Chrome插件。
其他方案思考:VSCode插件(先得确保团队用的编辑器统一,并且只能自动将色值转成CSS变量)
核心逻辑
核心逻辑:
-
找到色值对应的DOM结构,获取色值,并且给这个DOM新增点击事件
-
根据色值查找类名,要做到这一点我们需要手动把色值和类名的对应关系维护起来
-
执行复制操作
核心代码
json
{
"manifest_version": 3,
"name": "lanhu-color2class",
"version": "1.0.0",
"description": "蓝湖颜色转类名",
"icons": {
"16": "assets/icon.png"
},
"action": {
"default_title": "lanhu-color2class",
"default_icon": "assets/icon.png",
"default_popup": "popup.html"
},
"permissions": [
"scripting"
],
"host_permissions": [
"https://lanhuapp.com/",
"http://localhost/*",
"http://127.0.0.1/*"
],
"content_security_policy": {
"extension_pages": "script-src 'self'; object-src 'self'"
},
"content_scripts": [
{
"css": [
"content/style.css"
],
"js": [
"content/content.js"
],
"matches": [
"https://lanhuapp.com/*"
],
"all_frames": true,
"run_at": "document_end",
"match_about_blank": true
}
]
}
关键点在于content_scripts
的配置项,会在域名为https://lanhuapp.com/
的网页里注入插件内的content/style.css
和content/content.js
。
content/content.js
就是核心的逻辑:
js
// 色值和类名的对应关系
var colors = {
'#333333': [{
className: 'text-color-1',
desc: '标题颜色'
}],
'#666666': [{
className: 'text-color-2',
desc: '副标题颜色'
}],
'#f8f8f8': [{
className: 'border-color',
desc: '边框颜色'
}],
'#2878ff': [{
className: 'bg-primary',
desc: '主题背景色',
}, {
className: 'color-primary',
desc: '主题文字颜色'
}]
}
var domStr =
`<div id="dlg">
<ul>
</ul>
</div>`
// 创建 DOMParser 对象
const range = document.createRange();
const dom = range.createContextualFragment(domStr);
document.body.after(dom)
function doCopy(str) {
function copyToClipboard(text) {
var textarea = document.createElement("textarea"); //创建临时的textarea元素
textarea.value = text; //设置要复制的内容为指定的值
document.body.appendChild(textarea); //添加到页面上
textarea.select(); //选中输入框的内容
try {
var successful = document.execCommand('copy'); //执行复制命令
var msg = successful ? '成功' : '失败';
console.log('已复制到剪贴板', msg);
} catch (err) {
console.error('无法复制到剪贴板', err);
} finally {
document.body.removeChild(textarea); //移除临时的textarea元素
}
}
//调用函数并传递需要复制的字符串作为参数
copyToClipboard(str);
}
// 打开、关闭弹窗
function openDialog() {
$('#dlg').show()
}
function closeDialog() {
$('#dlg').hide()
}
function setDialogValue(colorDetail) {
var html = ''
for(var i = 0; i < colorDetail.length; i++) {
var item = colorDetail[i]
html += `<li>
<div>${item.desc}</div>
<div class="my_link" data-classname="${item.className}">复制</div>
</li>`
}
$('#dlg').find('ul').html(html)
}
function transformColor(color) {
var colorDetail = colors[color]
if(colorDetail) {
if(colorDetail.length == 1) {
// 色值只对应一个类名
console.log(`${colorDetail[0].desc}已复制,类名为${colorDetail[0].className}`)
doCopy(colorDetail[0].className)
} else {
// 色值对应多个类名 弹出一个弹窗,再去选择要复制的类名
setDialogValue(colorDetail)
openDialog()
}
} else {
// do nothing
console.log('该色值暂未收录,请检查或向UI确认')
}
}
// 给 copy_text 新增点击事件,copy_text就是蓝湖中色值的类名;
$('body').on('click', '.copy_text', function(e) {
var key = $(this).text().toLowerCase()
transformColor(key)
})
// 多个对应关系存在的时候,给弹出的弹窗绑定事件
$('#dlg').on('click', '.my_link', function() {
var copyText = $(this).attr('data-classname')
console.log(`已复制类名为${copyText}`)
doCopy(copyText)
closeDialog()
})
最终效果
点击F8F8F8
,直接复制了border-color
:

点击#2878FF
,可以选择复制bg-primary
或者color-primary
:

Demo
测试方法:
第一步:下载👆🏻的代码
第二步:Chrome打开插件管理页面:chrome://extensions/
第三步:设置为开发者模式,加载已解压的扩展程序,然后选中代码目录

第四步:打开蓝湖,在蓝湖的Demo项目里找到相关颜色并点击

后续完善
-
如果有CDN的话,可以把色值和类名的对应关系的json数据存起来,这样如果需要更新的话,就不用重新打包插件了;
-
如果有条件的话,可以把色值和类名的对应关系存在数据库中,提供增删改查接口,再配合popup.html,实现色值类名的快捷管理。