Emoji表情输入
常用的utf8编码,最多只会达到3字节,如MySQL的utf8编码。但像emoji表情等Unicode是4字节的(UCS-4),在编码为utf8时,也会占用4字节。在MySQL中,就要使用utf8mb4(most bytes 4)编码,否则插入时会报错。
当数据库不支持emoji时,前端如何实现拦截呢?
对于字符过滤,一般我们第一个想到的大多是正则表达式。然而,实际使用中,由于emoji表情的不断增加或正则表达式本身的缺陷,往往达不到过滤的效果(MySQL的utf8编码,并不是所有emoji都不支持,小于4字节的❎就是个例外,我们总不能数据库支持的字符都不给用吧)。
发现问题
欢迎来到王者荣耀😊😊 字符数量10,字符串长度12
一次开发中,使用了el-input的字符数统计属性show-word-limit,发现输入emoji表情统计到的字符数量和实际看到的字符数量不一致。
然后,尝试通过字符串分割成数组,再比较长度,发现str.split('')得到的数组长度和统计到的字符数是一样的,但是和看到的字符数量还是不一致。
var str = '欢迎来到王者荣耀😊😊'
var arr = str.split('')
console.log(str.length) // 12
console.log(arr.length) // 12
解决问题
那么,是否可以通过字符串的字符数量和字符串长度来判断是否输入了emoji表情呢?
要验证这个问题,关键的是获取到字符串中字符的数量。
那么如何获取字符串中字符的数量呢,通过研究(百度)发现,分割utf8字符串的正确方法是使用 Array.from(str) 而不是str.split('')。
其实,除了Array.from()之外,还有其他方法也可以实现,如:扩展运算符(...)和解构赋值。
var str = '欢迎来到王者荣耀😊😊'
// Array.from()
var arr2 = Array.from(str)
// 扩展运算符
var arr3 = [...str]
// 解构赋值
var [...arr4] = str
console.log(str.length) // 12
console.log(arr2.length) // 10
console.log(arr3.length) // 10
console.log(arr4.length) // 10
一个大胆的猜想
emoji表情判断,可以通过字符串长度和字符数量的比较判断是否存在emoji表情,当长度和数量不一致的时候,存在emoji表情。
function isEmojiStr(str) {
if (typeof (str) === 'string') {
const arr = Array.from(str);
if (str.length !== arr.length) {
return true;
}
}
return false;
}
- 控制台验证
console.log(isEmojiStr('欢迎来到王者荣耀😊😊'))
console.log(isEmojiStr('🐱🐉'))
console.log(isEmojiStr('欢迎来到王者荣耀'))
console.log(isEmojiStr('大家好@!¥%……&*(——+'))
console.log(isEmojiStr('ヾ(≧▽≦*)oφ(* ̄0 ̄)'))
console.log(isEmojiStr('₩㎝㎜㈤㈧㈦'))
console.log(isEmojiStr('❎'))
console.log(isEmojiStr('🚀'))
console.log(isEmojiStr('🅰'))
console.log(isEmojiStr('©'))
上图中❎、© 是utf8编码的MySQL支持的字符。
参考
# Emoji Unicode Tables
# 深入理解Emoji(一) —— 字符集,字符集编码
# 深入理解Emoji(二) —— 字节序和BOM
# 深入理解Emoji(三) —— Emoji详解