把vue文件中的style抽离到单独的文件

最近接到需求,要换肤,给系统增加主题的概念,让用户可以一键换肤。就想着参考element-ui中样式的管理方法,把所有样式都放到一起统一管理,而不是分散在vue文件中。然后就写了一个小工具来实现这个功能,基本可用

const path = require('path');
const fs = require('fs');
const compiler = require('vue-template-compiler');
const colors = [];
const reg = /(#[a-f0-9]{3.6})|(rgb[a]?\(.*\))/g; // 这个正则用来提取颜色值的,不完美,大体可用

let wd = process.argv[2] || '.';
wd = path.resolve(__dirname, wd);

if (process.argv[3] === 'color') {
	traverseDirectory(wd, analyzeColor);
	const cs = new Set(colors);
	console.log('所有颜色:', cs);
	return;
}
// 遍历目录,处理每一个vue文件
function handleDirectory(dirPath) {
	traverseDirectory(dirPath, handleSingleVue);
}

handleDirectory(wd);

// 遍历目录
function traverseDirectory(dirPath, cb) {
	const files = fs.readdirSync(dirPath);
	log(dirPath, ':');
	files.forEach(file => {
		log(file);
		const filePath = path.resolve(dirPath, file);
		if (!shouldHandle(file)) {
			log('不需要处理');
		} else if (isVue(file)) {
			log('vue文件');
			cb && cb(filePath);
		} else if (isDirectory(filePath)) {
			log('目录');
			traverseDirectory(filePath, cb);
		} else {
			log('不需要处理');
		}
	});
}

function handleSingleVue(filePath) {
	const content = fs.readFileSync(filePath, 'utf-8');
	const ret = compiler.parseComponent(content);
	if (ret.styles && ret.styles.length) {
		let str = `<template>${ret.template.content}</template>\r\n<script>${ret.script.content}</script>\r\n`;
		const styles = ret.styles.map((style, index) => {
			const stylePath = extractStyle(filePath, style, index);
			return `<style${style.lang && style.lang !== 'css' ? ' lang="' + style.lang + '"' : ''}${style.scoped ? ' scoped' : ''}>\r\n@import "${replaceSrc(stylePath.replace(/\\/g, '/'))}";\r\n</style>`;
		});
		str += styles.join('\r\n') + '\r\n';
		saveToFile(filePath, str);
	}
}


function replaceSrc(filePath) {
	const index = filePath.indexOf('/src');
	return '@' + filePath.substr(index + 4);
}

function extractStyle(filePath, styleObj, fileIndex) {
	const index = filePath.indexOf(path.sep + 'src');
	const styleFilePath = filePath.substr(0, index) + ['', 'src', 'styles', 'default-theme'].join(path.sep) + filePath.substr(index + 4).replace('.vue', (fileIndex === 0 ? '' : fileIndex) + '.' + styleObj.lang);

	saveToFile(styleFilePath, styleObj.content);
	const c = getAllColors(styleObj.content);
	if (c) {
		colors.push(...c);
	}
	return styleFilePath;
}

function saveToFile(pathName, content) {
	const dirs = pathName.split(path.sep);
	let tmpStr = '';
	for (let i = 0; i < dirs.length - 1; i++) {
		tmpStr += dirs[i] + path.sep;

		if (!fs.existsSync(tmpStr)) {
			fs.mkdirSync(tmpStr);
		}
	}
	fs.writeFileSync(pathName, content);
}


function log(str) {
	console.log(str);
}

function isVue(filePath) {
	return filePath && filePath.toLowerCase().endsWith('.vue');
}

function isDirectory(filePath) {
	const stat = fs.statSync(filePath);
	return stat.isDirectory();
}

function shouldHandle(filePath) {
	const excludedDirs = ['node_modules', 'dist', '.git'];
	if (filePath && (filePath[0] === '.' || excludedDirs.some(dir => filePath.indexOf(dir) !== -1))) {
		return false;
	}
	return true;
}

function getAllColors(content) {
	return content.match(reg);
}

function analyzeColor(filePath) {
	const content = fs.readFileSync(filePath, 'utf-8');
	const ret = compiler.parseComponent(content);
	(ret.styles || []).forEach(style => {
		const c = getAllColors(style.content);
		if (c) {
			colors.push(...c);
		}
	});
}

保存成extractStyle.js
公司电脑不能联网,又比着敲了一遍,注释实在是敲不动了!!

用法:

  • 在vue项目根目录下执行node extractStyle.js ./src,就会遍历src下面的vue文件,然后在src/styles/default-theme中创建对应的样式文件,同时把原来的vue文件中的样式提取出去,只留下@import ‘@/xxxxx’
  • 还提供了一个小工具,用来分析样式中使用的颜色值,有一点瑕疵,但是不影响使用, node extractStyle.js ./src color

由于项目代码审查不严格,我的项目中已经有200多个颜色值了,我都抓狂了

在这里插入图片描述
前面的路还很长啊!!!😦

如果有帮助,请点赞哦:)

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值