我有个气人的同事......

7,850 阅读4分钟

前段时间看到掘金上好几个 console 自定义的仓库玩法,就想到自己曾经也这么玩过。就想着把自己故事写出来。

曾经,我有个气人的同事,总是喜欢用 console.error() 来调试代码,搞得我和他合作,看到控制台老难受了,就为他特殊定制了一个工具库 console-custom。沉寂在个人仓库很久,前段时间看到别人也有类似仓库,也就想着把自己的也发出来。

其实,我个人不是很推荐在代码里 写 console.log 之类的来调试代码,更推荐去浏览器控制台去打断点来调试,更好的理清数据的流转,事件的先后顺序等。

背景

官方背景:

  • 方便大家调试代码的时候,在浏览器控制台输出自定义个性化日志。
  • 防止控制台输出密密麻麻的 console.log,一眼看不到想看的。
  • 防止某个气人的小伙伴老是使用 console.error,强迫症不允许。
  • ......

真实背景:

其实,是我之前有个小伙伴同事——“小白菜”(也是为啥函数名叫 blog 的原因之一,下边会看到),他调试代码,打印输出总是喜欢 console.error(),用完了还不自己清理,大家协同开发的时候,git pull 他的代码后,总是让人就很难受!看着一堆报错,一时半会看不清是程序自己的报错,还是调试的输出!强迫症就犯了!想骂街......

不......不......要冷静!

  • 编码千万行
  • 调试要输出
  • log不规范
  • 同事两行泪

效果

浏览器页面 page

tu1.jpg

浏览器控制台 console

image.png

有个重点、痛点是这个, console.log(111, 222, 333, 444, 555, 666, 777, 888, 999, 1111, 2222, 3333); 打印的数据多的时候不换行,需要找半天,我专门给处理成 分行, 一行一行展示了,这样好看清数据。

这个工具库有以下几个特点:

  1. 支持输入多个数据,并分行打印出来,并能看出是个整体
  2. 支持自己修改自己的默认样式部分,配置自己的默认部分
  3. 支持额外的自定义部分,拓展用户更多的玩法
  4. ......

其实 console 由于可以自定义,其实会有很多玩法,我个人在此主要的思路是

  1. 一定要简单,因为 console.log 本身就很简单,尽量不要造成使用者心智负担。
  2. 就简单的默认定制一个彩色个性化的部分,能区分出来,解决那个气人同事所谓的痛点就好。
  3. 代码要少,不要侵入,不要影响用户的业务代码

源码

此处源码有借鉴github 开源代码部分实现方式:

// src/utils/console-custom.js
const GourdBabyColorMap = new Map([
  ["1", "#FF0000"],
  ["2", "#FFA500"],
  ["3", "#FFFF00"],
  ["4", "#008000"],
  ["5", "#00FFFF"],
  ["6", "#0000FF"],
  ["7", "#800080"],
]);

const createBLog = (config) => {
  const logType = config.logType || "default";
  const username = config.username || "";
  const logName = config.logName || "";
  const usernameColor = config.usernameColor || "#41b883";
  const logNameColor = config.logNameColor || "#35495e";
  const padding = config.padding || 6;
  const borderRadius = config.borderRadius || 6;
  const fontColor = config.fontColor || "#FFFFFF";
  const usernameStyle = config.usernameStyle || "";
  const logNameStyle = config.logNameStyle || "";

  const logTemplate = (username = "myLog", logName = "") =>
    `${username ? '%c' + username : ''} ${logName ? '%c' + logName : ''} `;

  const customLog = (...data) => {
    console.log(
      logTemplate(username, logName),
      usernameStyle ? usernameStyle : `background: ${usernameColor}; padding: 6px; border-radius: 6px 0 0 6px;  color: #fff`,
      logNameStyle ? logNameStyle : `background: ${logNameColor}; padding: 6px; border-radius: 0 6px 6px 0;  color: #fff`,
      ...data
    );
  };

  const defaultLog = (...data) => {
    const len = data.length;
    if (len > 1) {
      data.map((item, index) => {
        let firstStyle = `
          background: ${GourdBabyColorMap.get(index % 7 + 1 +'')}; 
          padding: ${padding}px; 
          border-radius: 0 0;  
          color: ${fontColor}
        `;
        let secondStyle = `
          background: ${logNameColor}; 
          padding: ${padding}px; 
          border-radius: 0 0;  
          color: ${fontColor}
        `;
        if (index === 0) {
          firstStyle = `
            background: ${GourdBabyColorMap.get(index % 7 + 1 +'')}; 
            padding: ${padding}px; 
            margin-top: ${padding * 2}px;
            border-radius: ${borderRadius}px 0 0 0; 
            color: ${fontColor}
          `;
          secondStyle = `
            background: ${logNameColor}; 
            padding: ${padding}px; 
            margin-top: ${padding * 2}px;
            border-radius: 0 ${borderRadius}px 0 0;  
            color: ${fontColor}
          `;
        } else if (index === len -1) {
          firstStyle = `
            background: ${GourdBabyColorMap.get(index % 7 + 1 +'')}; 
            padding: ${padding}px; 
            margin-bottom: ${padding * 2}px;
            border-radius: 0 0 0 ${borderRadius}px;
            color: ${fontColor}
          `;
          secondStyle = `
            background: ${logNameColor}; 
            padding: ${padding}px; 
            margin-bottom: ${padding * 2}px;
            border-radius: 0 0 ${borderRadius}px 0;  
            color: ${fontColor}
          `;
        }
        console.log(
          logTemplate(username, `数据${index+1}`),
          firstStyle,
          secondStyle,
          item
        );
      });
    } else {
      const firstStyle = `
        background: ${usernameColor}; 
        padding: ${padding}px; 
        border-radius: ${borderRadius}px 0 0 ${borderRadius}px;  
        color: ${fontColor}
      `;

      const secondStyle = `
        background: ${logNameColor}; 
        padding: ${padding}px; 
        border-radius: 0 ${borderRadius}px ${borderRadius}px 0;  
        color: ${fontColor}
      `;

      console.log(
        logTemplate(username, logName),
        firstStyle,
        secondStyle,
        ...data
      );
    }
  };

  const log = (...data) => {
    switch(logType) {
      case 'custom':
        customLog(...data)
        break;
      default:
        defaultLog(...data)
    }
  };

  return {
    log,
  };
};

export default createBLog

API

唯一API createBLog(对!简单!易用!用起来没有负担!)

import createBLog from '@/utils/console-custom'

const myLog = createBLog(config)

配置 config: Object

一次配置,全局使用。(该部分是借鉴开源代码重构了配置内容)

配置项说明类型默认值
logTypelog 日志类型default、customdefault
usernamelog 的主人,也就是谁打的日志string-
logNamelog 的名字,也就是打的谁的日志string-
usernameColorusername 自定义背景颜色,接受 CSS background 的其他书写形式,例如渐变string#41b883
logNameColorlogName 自定义背景颜色,接受 CSS background 的其他书写形式,例如渐变string#35495e
paddingusername 和 logName 内边距,单位 pxnumber6
borderRadiususername 和 logName 圆角边框,单位 pxnumber6
fontColorusername 和 logName 字体颜色string#FFFFFF
usernameStyleusername 自定义样式,logType 为 custom 时候设置才生效,设置后则 usernameColor 的设置会失效string-
logNameStylelogName 自定义样式,logType 为 custom 时候设置才生效,设置后则 usernameColor 的设置会失效string-

基本用法 default

也是默认用法(default),同时也是最推荐大家用的一种方法。

vue2 版本

// main.js
import createBLog from '@/utils/console-custom'

const myLog = createBLog({
  username: "bigger",
  logName: "data",
  usernameColor: "orange",
  logNameColor: "#000000",
  padding: 6,
  borderRadius: 12,
  fontColor: "#aaa",
});

// 不需要使用时单独自定义 logName 的全局绑定
Vue.prototype.$blog = myLog.log;

// 需要使用时单独自定义 logName 的全局绑定
Vue.prototype.$nlog = (logName, ...data) => {
  myLog.logName = logName;
  myLog.log(...data);
};

// vue2 组件里边使用
// 同时输入多个日志数据,可帮用户按照行的形式分开,好一一对应看清 log
this.$blog(111, 222, 333, 444, 555, 666, 777, 888, 999, 1111, 2222, 3333);
this.$blog(111231231231231);

this.$nlog("logName", 2212121212122);

vue3 版本

// main.ts
import createBLog from '@/utils/console-custom'

const myLog = createBLog({
  username: "bigger",
  logName: "data",
  usernameColor: "orange",
  logNameColor: "#000000",
  padding: 6,
  borderRadius: 12,
  fontColor: "#aaa",
});

app.config.globalProperties.$blog = myLog.log;

// vue3 组件里边使用
import { getCurrentInstance } from 'vue'

export default {
  setup () {
    const { proxy } = getCurrentInstance()

    proxy.$blog(111, 222, 333, 444, 555, 666, 777, 888, 999, 1111, 2222, 3333);
    proxy.$blog(111231231231231);

    proxy.$nlog("logName", 2212121212122);
  }
}

自定义用法 custom

这部分我没有很多玩法,下边的例子也是借鉴别人的,主要全靠用户自己扩展 css 样式了。做一套自己喜欢的样式。

// main.js

// ....
Vue.prototype.$clog = (logName, ...data) => {
  myLog.logType = "custom";
  myLog.logName = logName;
  myLog.usernameStyle = `text-align: center;
    padding: 10px;
    background-image: -webkit-linear-gradient(left, blue,
        #66ffff 10%, #cc00ff 20%,
        #CC00CC 30%, #CCCCFF 40%,
        #00FFFF 50%, #CCCCFF 60%,
        #CC00CC 70%, #CC00FF 80%,
        #66FFFF 90%, blue 100%);`;
  myLog.logNameStyle = `background-color: #d2d500;
    padding: 10px;
    text-shadow: -1px -1px 0px #e6e600,-2px -2px 0px #e6e600,
    -3px -3px 0px #e6e600,1px 1px 0px #bfbf00,2px 2px 0px #bfbf00,3px 3px 0px #bfbf00;`;
  myLog.log(...data);
};

// 提供的其他 css 样式
myLog.usernameStyle = `background-color: darkgray;
    color: white;
    padding: 10px;
    text-shadow: 0px 0px 15px #00FFFF,0px 0px 15px #00FFFF,0px 0px 15px #00FFFF;`;
myLog.logNameStyle = `background-color: gray;
  color: #eee;
  padding: 10px;
  text-shadow: 5px 5px 0 #666, 7px 7px 0 #eee;`;

myLog.usernameStyle = `background-color: darkgray;
    color: white;
    padding: 10px;
    text-shadow: 1px 1px 0px #0000FF,2px 2px 0px #0000FF,-1px -1px 0px #E31B4E,-2px -2px 0px #E31B4E;`;
myLog.logNameStyle = `font-family: "Arial Rounded MT Bold", "Helvetica Rounded", Arial, sans-serif;
    text-transform: uppercase;/* 全开大写 */
    padding: 10px;
    color: #f1ebe5;
    text-shadow: 0 8px 9px #c4b59d, 0px -2px 1px #fff;
    font-weight: bold;
    letter-spacing: -4px;
    background: linear-gradient(to bottom, #ece4d9 0%,#e9dfd1 100%);`;
// ....

其中渐变色的玩法

myLog.usernameStyle = `background-image: linear-gradient(to right, #ff0000, #ff00ff); padding: 6px 12px; border-radius: 2px; font-size: 14px; color: #fff; text-transform: uppercase; font-weight: 600;`;
myLog.logNameStyle = `background-image: linear-gradient(to right, #66ff00	, #66ffff); padding: 6px 12px; border-radius: 2px; font-size: 14px; color: #fff; text-transform: uppercase; font-weight: 600;`;

其中输出 emoji 字符

this.$nlog("😭", 2212121212122);
this.$nlog("🤡", 2212121212122);
this.$nlog("💩", 2212121212122);
this.$nlog("🚀", 2212121212122);
this.$nlog("🎉", 2212121212122);
this.$nlog("🐷", 2212121212122);

小伙伴们你肯定还有什么好玩的玩法!尽情发挥吧!

最后

还是想极力劝阻那些用 console.error() 调试代码的人,同时也能尽量少用 console 来调试,可以选择控制台断点、编译器断点等。还是不是很推荐使用 console 来调试,不过本文也可以让大家知道,其实 console 还有这种玩法。如果写 JS 库的时候也可以使用,让自己的库极具自己的特色。