一. 前言
在日常开发中,前端最常用的调试以及输出手段就是往控制台
输出对应的内容,以此来判断输出的内容准确性
和合理性
。
不仅仅在开发环境
,有些内容在生产环境
也可以在控制台打印出来。比如当前版本信息
、一些活动的提示
等等。

不仅如此,一些大公司,比如百度、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的大小、颜色、边框等。这时候就需要实现一个方法,用来显示用户自定义的内容和样式
。
我的想法,是传入一个数组对象
,数组对象里面包含content
和style
两个字段。两者之间是 一一对应
的关系。
[{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
的封装。但是还有很多优化
的地方,还有图片
、链式调用
没有实现(放在下一期)。最终的代码也会放到下一期。欢迎大家指出问题。