- 背景:應用系統中存在多個建立實體表單,表單填寫時,在填寫中文名稱後,要填寫對應的英文名作為標識或資料庫查詢索引。
- 需求:填寫中文名的同時,系統自動生成英文名並填充到表單中,輔助使用者操作,節約操作時間。
實現效果
方案調研
對需求進行分析後,對於如何將中文名翻譯成英文字串,調研以下方案:
- 呼叫翻譯引擎
優點:翻譯準確,對於短句也能翻譯
缺點:部署難度大,需要捆綁翻譯引擎 - 呼叫開放API(谷歌翻譯/百度翻譯等)
優點:能完成翻譯功能
缺點:可能需要付費/開發者帳號等,需要整合成本,需要私有化部署版本時(無法連線外網)可能無法實現 - 使用音譯外掛(參考:https://github.com/dzcpy/transliteration)
優點:輕量,整合簡單,有一定可擴充套件性,可離線
缺點:無法翻譯,只能音譯(會將“你好”翻譯成“ni_hao”而不是“hello"),使標識的可讀性和語義性下降。
以上三種僅為中轉英的方法不同,均可實現功能。本次方案暫使用第三種。
實現方案
- 分析:該功能需要增加到多個表單中,如果為每個需要新增的元件都增加相應邏輯,侵入性較強,也不好維護。
- 邏輯提煉:
- 為中文名的輸入框繫結監聽事件,監聽輸入,取得該input框輸入的值
- 將第一步中獲得的中文值轉化成英文字串
- 將英文字串寫入到英文名輸入框中
思路: 為表單新增vue
自定義指令,通過取子節點(根據虛擬節點層級,vnode
的子級)的方法,獲取到需要操作的dom元素,再在指令邏輯中進行邏輯處理。
程式碼實現
指令定義
- 定義
v-transliterate
指令(vue自定義指令的定義和使用可參考官方文件,此處不做贅述) transliterate.js
import { transliterate as tr, slugify } from 'transliteration'
export default {
inserted(el, binding, vnode) {
let sourceInputEl = vnode.componentInstance.$children.find(item => item.prop === 'name').$children[1].$el.children[0]
let targetInputEl = vnode.componentInstance.$children.find(item => item.prop === 'key').$children[1].$el.children[0]
let isFirstInput = true;
sourceInputEl.addEventListener('keyup', () => {
// 判斷當前標識是否已填寫,若已填寫,則不再根據中文名稱生成
let isEmpty = !targetInputEl.value;
if (isEmpty || !isFirstInput) {
// 一定延遲處理,使用者使用幾乎無感知
setTimeout(() => {
let transValue = slugify(sourceInputEl.value, { separator: '_' });
let inputEvt = new InputEvent('input', {
inputType: 'insertText',
data: transValue,
dataTransfer: null,
isComposing: false
});
targetInputEl.value = transValue;
targetInputEl.dispatchEvent(inputEvt);
isFirstInput = false;
}, 500);
}
})
}
}
注意事項
1、transValue的生成可根據前面所說的不同方案,更改生成的方法。
2、兩個input 元素是根據prop來篩選的,程式碼中硬編碼為”name“ -中文名 和”key“ 英文名,可根據需求調整,也可以根據指令方法入參的binding賦值。由於本專案中所有表單prop都是固定的,所以沒有寫相應邏輯。
3、keyup
事件可根據需求更改為blur
事件,對於呼叫後臺api獲值,可考慮改為blur,降低頻繁請求。
4、執行 targetInputEl.value = transValue;
後,頁面上顯示已經改變,但點選儲存表單時仍然會觸發空值校驗,懷疑是因為該賦值沒有重新整理到虛擬節點的model中,故而使用 targetInputEl.dispatchEvent(inputEvt);
方法模擬輸入事件,觸發值的重新整理。
5、isEmpty
空值校驗,避免使用者在填寫表單時先填寫了英文名,再填寫中文名時,英文名被覆蓋。邏輯一般限定標識生成後就不允許修改,該方法也規避了修改時的英文名跟著中文名修改的問題。
6、使用transliterate
可定義配置字典,實現常用中-英單詞的翻譯,但仍然無法替代翻譯引擎。配置邏輯參考github上的README即可。
slugify.config({ replace: [['世界','world'],['你好','hello']] });
指令使用
需要用該功能的地方,在表單元素增加該指令即可。
總結
以上就是實現全過程,如果有更好的實現方法,請留言告訴我哦~