Vue | 指令實現自動翻譯填充英文名功能

Ygria發表於2021-05-23
  • 背景:應用系統中存在多個建立實體表單,表單填寫時,在填寫中文名稱後,要填寫對應的英文名作為標識或資料庫查詢索引。
  • 需求:填寫中文名的同時,系統自動生成英文名並填充到表單中,輔助使用者操作,節約操作時間。

實現效果

轉全拼

轉英文(偽)

方案調研

對需求進行分析後,對於如何將中文名翻譯成英文字串,調研以下方案:

  • 呼叫翻譯引擎
    優點:翻譯準確,對於短句也能翻譯
    缺點:部署難度大,需要捆綁翻譯引擎
  • 呼叫開放API(谷歌翻譯/百度翻譯等)
    優點:能完成翻譯功能
    缺點:可能需要付費/開發者帳號等,需要整合成本,需要私有化部署版本時(無法連線外網)可能無法實現
  • 使用音譯外掛(參考:https://github.com/dzcpy/transliteration)
    優點:輕量,整合簡單,有一定可擴充套件性,可離線
    缺點:無法翻譯,只能音譯(會將“你好”翻譯成“ni_hao”而不是“hello"),使標識的可讀性和語義性下降。

以上三種僅為中轉英的方法不同,均可實現功能。本次方案暫使用第三種。

實現方案

  • 分析:該功能需要增加到多個表單中,如果為每個需要新增的元件都增加相應邏輯,侵入性較強,也不好維護。
  • 邏輯提煉:
  1. 為中文名的輸入框繫結監聽事件,監聽輸入,取得該input框輸入的值
  2. 將第一步中獲得的中文值轉化成英文字串
  3. 將英文字串寫入到英文名輸入框中
    思路: 為表單新增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']] });

指令使用

需要用該功能的地方,在表單元素增加該指令即可。
指令使用

總結

以上就是實現全過程,如果有更好的實現方法,請留言告訴我哦~

相關文章