問題場景
- 后台不提供富文本存儲,所以emoji表情入庫會報錯
- 需求要求前端在輸入的時候過濾掉表情符號
- 全局的input 和富文本textarea輸入框都需要過濾emoji表情
問題分析
1.每一個input寫事件寫正則校驗代碼量實在太多了還很麻煩;所以想用自定義全局指令,就不需要每個用到的地方都去引入了。
2.emoji太多了,並且輸入法的emoji、mac自帶的emoji 、windows自帶的emoji是不一致的。全部emoji列出來一一過濾替換實在不現實,后來發現emoji表情都是2個字符的長度,其他鍵盤輸入都是一個字符的長度。因此用字符長度來校驗可行
3.需要在輸入的時候過濾掉表情符號,那么就需要在(keyup)鍵盤觸發的時候監聽觸發過濾事件
代碼實現
js實現輸入框監聽方法 common/utils/emoji'
const findEle = (parent, type) => {
return parent.tagName.toLowerCase() === type ? parent : parent.querySelector(type)
}
const trigger = (el, type) => { // 給元素綁定事件
const e = document.createEvent('HTMLEvents')
e.initEvent(type, true, true)
el.dispatchEvent(e)
}
const emoji = {
// el:指令所綁定的元素,可以用來直接操作 DOM。
// vnode:Vue 編譯生成的虛擬節點
bind: function (el, binding, vnode) { // 指令第一次綁定到元素時調用
// 判斷是否是emoji圖標
const isEmoji = char => {
// 表情都是2個字符
return char.length > 1;
}
const emoji2empty = str => { // emoji圖標都替換成空字符串‘’
return Array.from(str)
.filter(c => !isEmoji(c)).join('')
}
let $inp = findEle(el, 'input') || findEle(el, 'textarea') // 判斷綁定元素是否是input輸入框或者富文本輸入框
el.$inp = $inp
$inp.handle = function () {
let val = $inp.value
$inp.value = emoji2empty(val) // 監聽輸入框的emoji圖標轉換成空
trigger($inp, 'input')
}
$inp.addEventListener('keyup', $inp.handle) // el添加鍵盤監聽事件keyup
$inp.addEventListener('blur', $inp.handle) // el添加鍵盤失焦事件blur
},
unbind: function (el) { // 只調用一次,指令與元素解綁時調用。
el.$inp.removeEventListener('keyup', el.$inp.handle)
el.$inp.removeEventListener('blur', el.$inp.handle)
},
}
export default emoji
入口文件引入emoji並且全局注入指令
Vue.directive( id, [definition] )
id: 為指令唯一id
{Function | Object} [definition] 注冊的指令
一個指令定義對象可以幾個鈎子函數 (均為可選):這里使用到bind和unbind
bind:只調用一次,指令第一次綁定到元素時調用。在這里可以進行一次性的初始化設置。
unbind:只調用一次,指令與元素解綁時調用。
import emoji from './common/utils/emoji';
Vue.directive('emoji', emoji)
使用場景
// 在input框添加v-emoji指令既可
<a-input
:maxLength="50"
v-emoji
autocomplete="off"
placeholder="請輸入名稱"
v-model= "form.label" />