在项目中,让你的console.log输出更炫酷~~

一. 前言

在日常开发中,前端最常用的调试以及输出手段就是往控制台输出对应的内容,以此来判断输出的内容准确性合理性

不仅仅在开发环境,有些内容在生产环境也可以在控制台打印出来。比如当前版本信息、一些活动的提示等等。

不仅如此,一些大公司,比如百度、b站、搜狐等也会在控制台放置一些企业以及公司信息等。

好,多的不bb,实现一个hooks在项目中使用。

二. 基本语法

console方法其实有很多,这里我就挑几个我觉得比较常见好用的方法讲一下。具体可以去看文档:console的用法。

2.1 console.log

这个应该是用的最多。

js 复制代码
console.log(123)       // 123

但是他可以使用 占位符 实现高级一点的用法。

  • %s : 用于字符串占位。
  • %d : 用于整数占位。
  • %f : 用于浮点数
  • %o : 用于对象(显示对象类型,及其属性)。
  • %c : 用于css样式输入(类似于内联样式的写法)。

这里要注意一点:

占位符参数需按 顺序传递,未传递参数时默认使用空字符串。

举几个例子玩一玩:

js 复制代码
let version = '1.2.3'
let int = 200.0
let obj = {name: 'xmTeacher', age: 18}
console.log(`version: %s`, version)

console.log(`%d`, int)   // 200  只会打印整数部分
console.log(`%f`, int)   // 200.1 全部打印
console.log(`%cversion: %s`, 'color: #67C23A', version)
console.log(`%d`, obj)   // NaN
console.log(`%o`, obj)   // {name: 'xmTeacher', age: 18}

2.2 console.assert

接受两个参数:

如果第一个为false,则会将一个错误消息输出到控制台。

js 复制代码
let a = document.getElementById('id1')
let b = undefined
let c = null

console.assert(a, 'id不存在')
console.assert(b, 'b不存在')
console.assert(c, 'c不存在')

2.3 console.dir

如果我们想更细一步查看对象内部的方法和属性,这个就很好用。

js 复制代码
let obj = {name: 'xmTeacher', age: 18}
console.dir(obj)

ps: 个人觉得这个方法,更适合用于数组和对象中获取更多信息,例如原型等。

2.4 console.error

这个没什么好说的,就是往控制台输入一个错误信息。

js 复制代码
let obj = {name: 'xmTeacher', age: 18}
console.error(obj)

三. 封装通用的hooks

虽然,console方法有很多,但是用的最多的还是,console.log。我这边封装的hooks还是以这个方法为主。

现在我们来一步步实现一下。

使用的项目环境:Vue3.0 + Ts

3.1 实现效果

  • 美化控制台提示信息打印
  • 支持定制化css样式
  • 区别生产环境和开发环境使用
  • 支持链式调用
  • 支持图片和特殊字符

3.2 美化控制台提示信息打印

3.2.1 通用方法

新建一下consoleExtension.ts,里面写一个函数:

ts 复制代码
export const consoleExtension = () => {
}

根据element-ui的辅助颜色,我想把打印信息类型分为5种。

  • 成功(success)
  • 警告(warning)
  • 危险(error)
  • 平常(normal)
  • 主要(primary)

然后我们在consoleExtension里面返回这五个函数

js 复制代码
const success = () => {

}

const warning = () => {

}

const error = () => {

}

const normal = () => {

}

const primary = () => {

}

export const consoleExtension = () => {
  return {
    success: () => success(),
    warning: () => warning(),
    error: () => error(),
    normal: () => normal(),
    primary: () => primary()
  }
}

其实这5个方法,内部实现的逻辑都是一样的。所以写一个公共方法

ts 复制代码
const basePrint = (title: string, content: string, color: string) => {
    const titleStyle = title ? `background:${color}; border:1px solid ${color}; padding: 1px; color: #fff; font-size: 14px` : ''
    const contentStyle = content ? `border:1px solid ${color}; padding: 1px; color: ${color}; font-size: 14px` : ''
    console.log(`%c ${title} %c ${content}`, `${titleStyle}`, `${contentStyle}`)
}

代码很简单: 就是根据不同的类型,选择不同的颜色,然后展示内容

之后,我们在五个方法里面使用一下:

ts 复制代码
// 枚举一下颜色
enum Color {
 SUCCESS = '#67C23A',
 WARNING = '#E6A23C',
 DANGER = '#F56C6C',
 NORMAL = '#909399',
 PRIMARY = '#409EFF'
}

const success = (title: string, content: string) => {
  basePrint(title, content, Color.SUCCESS)
}

const warning = (title: string, content: string) => {
  basePrint(title, content, Color.WARNING)
}

const error = (title: string, content: string) => {
  basePrint(title, content, Color.DANGER)
}

const normal = (title: string, content: string) => {
  basePrint(title, content, Color.NORMAL)
}

const primary = (title: string, content: string) => {
  basePrint(title, content, Color.PRIMARY)
}

完成之后,我们在项目里面引用一下,回到app.vue页面:

js 复制代码
import { consoleExtension } from './hooks/consoleExtension'

const { success, warning, error, normal, primary } = consoleExtension()
success('success', '这是个成功的信息')
warning('warning', '这是个警告的信息')
error('error', '这是个错误的信息')
normal('normal', '这是个普通的信息')
primary('primary', '这是个常用的信息')

我们看一下页面的效果:

3.2.2 自定义样式

有些时候,用户可能想要自己设置console的大小、颜色、边框等。这时候就需要实现一个方法,用来显示用户自定义的内容和样式

我的想法,是传入一个数组对象,数组对象里面包含contentstyle两个字段。两者之间是 一一对应 的关系。

[{content: '', style: ''}, {content: '', style: ''}, ...]

同时还提供一个简便的写法,通过传入字符串的方式。例如下面的例子:

'cotent=信息1&style={background: #fff},content=信息2&style={color: #333; padding: 1px}'

这种写法注意的是:

  • &链接的是同一对content和style。
  • ,是分割不同对的信息。

我们来实现一下。

第一步:处理 数组类型 。新建一个函数custom

ts 复制代码
const custom = (express: {content: string, style: string}[] | string) => {
    if (typeof === 'string') {
      // 处理字符串类型
    }
    else {
      // 处理array
      arrayToPrintContent(express)
    }
}

arrayToPrintContent这个方法,主要就是遍历express,然后把内容样式分别return出来,最后在console里面显示。

ts 复制代码
const arrayToPrintContent = (array: {content: string, style: string}[]): {content: string[], color: string} => {
  let contentString: string[] = []
  let colorString = ''
  array.forEach(item => {
    colorString = `${colorString} ` + `%c ${item.content}`   // 用%c链接在一起
    contentString.push(item.style)   // 这个地方要用数组
  })
  return {
    content: contentString,
    color: colorString
  } 
}

这里注意一点:因为console.log(color, content1, content1, ...),第一位参数是颜色占位符(这个是固定的),但是后面有多少位参数(有多少个content)这个取决于用户的自定义。所以我们这里用数组存储起来,然后使用的时候,直接解构

回到custom函数中:

ts 复制代码
  const {content, color} = arrayToPrintContent(strArr)
  console.log(color, ...content)   // 这里用扩展运算符把参数展开

第二步: 处理一下 字符串 。这里的想法是把字符串直接转为array: {content: string, style: string}[],这样就可以复用数组处理的逻辑了。

ts 复制代码
const matchStrToArray = (str: string) => {
  const strArr = str ? str.split(',') : []
  const result: {content: string, style: string}[] = []
  strArr.forEach((cur: string) => {
    const _arr = cur.split('&');
    const content = _arr.length > 0 ? _arr[0].split('=').length > 0 ? _arr[0].split('=')[1] : '' : ''
    const style = _arr.length > 1 ? _arr[1]!.match(/\{([^{}]*)\}/g)!.map((match: string) => match.slice(1, -1))[0] : ''
    result.push({
      content, style
    })
  })
  return result
}

主要的逻辑就是按照&=分割字符串,然后正则匹配style

然后我们在custom里面加一下:

ts 复制代码
const custom = (express: {content: string, style: string}[] | string) => {
  let strArr: {content: string, style: string}[]
  if (typeof express === 'string') {
    const res = matchStrToArray(express)
    strArr = res
  }
  else {
    strArr = express
  }
  const {content, color} = arrayToPrintContent(strArr)
  console.log(color, ...content)
}

我们在页面上使用一下:更新App.vue文件:

js 复制代码
custom([{content: '信息1', style: 'color: blue'}, {content: '信息2', style: 'background: #fff'}])
custom('cotent=信息3&style={background: #fff; font-size: 14px},content=信息4&style={color: #F56C6C; padding: 1px}')

3.2.3 美化复杂类型打印

其实数组类型用console自带的console.table类型就很好了,样式也美观。举个例子:

c 复制代码
const array = [1, 2, 3, 4]
const array2 = [{name: '111', age: 20, sex: 'jj'}, {name: '222', age: 20, sex: 'njj'}, {name: '333', age: 20, sex: 'jj'}]

console.table(array)
console.table(array2)

效果反正我是挺满意的。

这里就简单处理一下对象的console显示。(不考虑对象嵌套的问题,后续可以补上)

新建一个函数complicated

ts 复制代码
const complicated = (express: any[] | {}) => {
  if (Array.isArray(express)) {
    console.table(express)
  }
  else {
    const customArray = Object.entries(express).map(([key, value]) => ({
      id: key,
      value: value,
    }));
    console.table(customArray)
  }
}

然后更新一下custom文件:

js 复制代码
export const consoleExtension = () => {
  return {
    success: (title: string, content: string) => success(title, content),
    warning: (title: string, content: string) => warning(title, content),
    error: (title: string, content: string) => error(title, content),
    normal: (title: string, content: string) => normal(title, content),
    primary: (title: string, content: string) => primary(title, content),
    custom: (array: {content: string, style: string}[] | string) => custom(array),
    complicated: (express: any[] | {}) => complicated(express)
  }
}

最后在App.vue里面用一下:

js 复制代码
const array = [{name: '111', age: 20, sex: 'jj'}, {name: '222', age: 20, sex: 'njj'}, {name: '333', age: 20, sex: 'jj'}]
const obj = {name: '111', age: 20, sex: 'jj', gb: 'gb'}

complicated(array)
complicated(obj)

3.2.4 环境区分

开发中,console一般用于开发环境生产环境上显示的很少。(有些严格的代码提交规则是不允许提交console的)。但是不影响我们实现一下这个功能。

我们可以通过 import.meta.env.MODE 来区分环境。

我们写一个函数isShowEnv:

ts 复制代码
const isShowEnv = () => {
  return import.meta.env.MODE === 'production'  // 区分生产和开发环境
} 

但是光有这个还不够,可能会出现,某些信息需要打印在生产环境的控制台上。所以加一个用户自定义是否打印的标识sProd就好。

之后在方法里面加一个判断:

js 复制代码
const primary = (title: string, content: string, sProd?: boolean = false) => {
  if (!sProd && isShowEnv()) return;
  basePrint(title, content, Color.PRIMARY)
}

Ps: 这里要注意,如果在webpack或者Vite中用 插件 去除掉console,这个是不起作用的。

四. 总结

简单的实现了一下console的封装。但是还有很多优化的地方,还有图片链式调用没有实现(放在下一期)。最终的代码也会放到下一期。欢迎大家指出问题。

相关推荐
谜亚星3 分钟前
vue和react组件更新的一点思考
前端·前端框架
清秋8 分钟前
全网最全 ECMAScript 攻略( 更新至 ES2025)
前端·javascript·ecmascript 6
puffysang3311 分钟前
Android paging3实现本地缓存加载数据
前端
拉罐17 分钟前
React Query:彻底解决 React 数据获取难题的强大利器
前端
一涯1 小时前
用python写一个抓取股市关键词的程序
前端·python
情绪的稳定剂_精神的锚1 小时前
git提交前修改文件校验
前端
Moonbit1 小时前
MoonBit 作者寄语 2025 级清华深圳新生
前端·后端·程序员
前端的阶梯1 小时前
开发一个支持支付功能的微信小程序的注意事项,含泪送上
前端·后端·全栈
Juchecar1 小时前
Node.js package.json 配置详解 + TypeScript + ES Module 集成指南
javascript
李明卫杭州1 小时前
深入理解CSS变量(Custom Properties)
前端·javascript