今天看`简书`文章,习惯性的打开了开发者工具,于是发现了意见有意思的事,在console面板,发现了如下的日志:
??? 这 ... 有点意思。
如果上面的图片,不能引起你的兴趣,那么你可以再看看这个:
我用 console.log 不是一次两次了,但从来没有意识到,或者曾经知道,后来却忘记了,原来,我们可以通过参数指定 console.log 记录信息样式。
下面,我们来聊聊console.log格式化那点事。通过 console.log 的 MDN 文档(https://developer.mozilla.org/en-US/docs/Web/API/Console),我们看到,记录日志的时候,可以通过 '%c' 字符串替换,来修改 console 输出的样式,可用的样式属性列表如下:
background and its longhand equivalents.
border and its longhand equivalents
border-radius
box-decoration-break
box-shadow
clear and float
color
cursor
display
font and its longhand equivalents
line-height
margin
outline and its longhand equivalents
padding
text-* properties such as text-transform
white-space
word-spacing and word-break
writing-mode
举个例子:
console.log( "%cMy document: %o", "color: red;", document );
以上代码,我们通过 '%c' 指定了 'My document:' 文本的颜色,'%o' 表示输出一个对象,即将 document 以对象形式输出。其中,后面两个参数的顺序,要和前面字符串替换标识的顺序保持一致。
将上面代码输入命令行,可以看到输出如下:
我们可以看到,'My document:' 为红色,并且 document 显示了其结构。接下来,让我们试试其他属性:
<!doctype html><html lang="en"><head> <meta charset="utf-8" /> <title>用 CSS 控制 console.log() 的输出样式 </title></head><body> <h1> 用 CSS 控制 console.log() 的输出样式 </h1> <script type="text/javascript"> console.log("%c修改文本颜色","color: orange;" ); console.log("%c这个就是%c文章开始时的效果","padding: 1px;" +"border-radius: 3px 0 0 3px;" +"color: #fff;" +"background: #606060;","padding: 1px;" +"border-radius: 0 3px 3px 0;" +"color: #fff;" +"background: #42c02e;" ); console.log("%c改个背景试试","display: inline-block ; background-color: #606060;" +"background-size: cover ; padding: 10px 175px 158px 10px ; " +"border: 2px solid black ; font-size: 11px ; line-height: 11px ; " +"font-family: monospace ;" );</script></body></html>
上面代码,再 chrome 中运行结果如下:
目前看起来,效果还算不错,对吧,但是,对于日志样式,我们可以做的更多,目前来看,我们要把css字符串传入 console.log 函数中,显得有点冗长,幸运的是,我们是程序员,可以封装一下。封装的第一步,是先做一个能够替换基础 console 各个函数的对象,他应该有如下函数(可以更多):
echo.log()
echo.error()
echo.warn()
echo.trace()
echo.group()
echo.groupEnd()
而且,就像 console 相关函数,echo 对象的函数也是动态的,可以接收多个参数的。不同之处在于,echo 可以有很多的扩展函数,用于将输入格式化为需要的样式,如:
echo.asAlert()
echo.asWarning()
接下来,让我们实现它:
<!doctype html><html lang="en"><head> <meta charset="utf-8" /> <title>用 CSS 控制 console.log() 的输出样式 </title></head><body> <h1> 用 CSS 控制 console.log() 的输出样式 </h1> <script type="text/javascript"> // 提供特殊格式日志api。 var echo = (function () {var queue = [];var ECHO_TOKEN = {};var RESET_INPUT = "%c ";var RESET_CSS = ""; // 错误格式化声明function alertFormatting(value) { queue.push({ value: value, css: "display: inline-block ;" +"background-color: #e0005a;" +"color: #ffffff;" +"font-weight: bold;" +"padding: 3px 7px 3px 7px;" +"border-radius: 3px 3px 3px 3px ;" }); return (ECHO_TOKEN); } // 警告格式化声明function warningFormatting(value) { queue.push({ value: value, css: "display: inline-block;" +"background-color: gold;" +"color: black;" +"font-weight: bold;" +"padding: 3px 7px 3px 7px;" +"border-radius: 3px 3px 3px 3px;" }); return (ECHO_TOKEN); } // 为 console 函数提供一个 echo-based 代理// 本函数使用了一个内部队列用在调用日志函数之// 前的预处理日志格式。function using(consoleFunction) { function consoleFunctionProxy() { // 遍历传入参数,我们要构建一个输入参数数组input和// 一个字符串参数输入数组modifiers。// 在最后,input 数组中的元素将被合并为一个字符串,// 用作目标函数的第一个参数,modifiers// 数组中的元素将回被作为目标函数的后面的参数。// // 注意:对于每一个input和modifiers对,我们都要添加// 一个重置标识,以不至于影响之后输出的样式。var inputs = [];var modifiers = []; for (var i = 0; i < arguments.length; i++) { // 当接收到的参数是我们定义的特殊对象(用于标识特殊格式的对象) // 时,我们应该进行参数预处理,以进行格式化输出。 if (arguments[i] === ECHO_TOKEN) {var item = queue.shift(); inputs.push(("%c" + item.value), RESET_INPUT); modifiers.push(item.css, RESET_CSS); } else {// 对于其他参数,我们直接输出var arg = arguments[i]; if ( (typeof(arg) === "object") || (typeof(arg) === "function")) { inputs.push("%o", RESET_INPUT); modifiers.push(arg, RESET_CSS); } else { inputs.push(("%c" + arg), RESET_INPUT); modifiers.push(RESET_CSS, RESET_CSS); } } } consoleFunction(inputs.join(""), ...modifiers); // 在最后,我们重置参数数组。 queue = []; } return consoleFunctionProxy; } return ({ // Console(ish) 相关函数. log: using(console.log), warn: using(console.warn), error: using(console.error), trace: using(console.trace), group: using(console.group), groupEnd: using(console.groupEnd), // 格式化函数 asAlert: alertFormatting, asWarning: warningFormatting }); })();</script></body></html>
上面代码做的事可能不是很容易识别。简单的描述一下就是格式化函数asAlert() 和 asWarning() 把输入的字符串值以及其样式信息存储对象添加到了一个内部的队列中,然后代理函数通过解析队列中的值,并生成格式化字符串以及其他参数,然后将其传入 console 相关函数中。
如果我们在 Chrome 中运行上面页面的时候,输入如下代码:
// 试试多种格式连接输出echo.log( echo.asAlert("This is great!"), "Right!", {"I am" : "an object" }, null, ["an array"], function amAnFunction() {}, echo.asWarning("I mean, right?!?!") ); echo.log();// 再试试其他样例echo.group(echo.asWarning("Arnold Schwarzenegger Movies")); echo.log("The Running Man"); echo.log( "Terminator 2", echo.asAlert("Amazing!"), echo.asWarning("TOP 100") ); echo.log("Predator"); echo.log("Twins", echo.asWarning("TOP 50")); echo.groupEnd(); echo.log(); echo.log( echo.asAlert("Winner Winner"), "Chicken dinner!");
我们在开发面包中就可以看到如下输出:
到此为止,我们发现,再也不用为怎么拼接样式感到烦心了,所有样式都被封装到了代理对象中。