整合營銷服務(wù)商

          電腦端+手機(jī)端+微信端=數(shù)據(jù)同步管理

          免費(fèi)咨詢熱線:

          好煩,怎么輸入拼音的過程也會觸發(fā)input事件!!!

          好煩,怎么輸入拼音的過程也會觸發(fā)input事件!!!



          在前面

          input輸入框大家應(yīng)該都很熟悉了吧,不知道大家有沒有遇到過這樣的一種情況:如上圖,在中文輸入過程中,輸入的拼音也會觸發(fā)input框的input事件,有些時(shí)候我們并不希望在中文輸入的過程中拼音觸發(fā)input事件。

          在日常開發(fā)中,輸入框是一個(gè)常見的組件,但是在拼音輸入過程中,每次輸入都會觸發(fā)input事件,這可能會導(dǎo)致不必要的操作。本文將介紹一種解決該問題的Vue指令,使得在拼音輸入過程中不會觸發(fā)input事件,從而優(yōu)化輸入框體驗(yàn)。

          效果展示

          實(shí)現(xiàn)原理

          1、compositionstart和compositionend事件

          我們需要了解compositionstart和compositionend兩個(gè)事件。當(dāng)用戶開始輸入拼音時(shí),會觸發(fā)compositionstart事件,此時(shí)輸入框的值并沒有真正改變。隨著輸入的進(jìn)行,最終會觸發(fā)compositionend事件,此時(shí)輸入框的值才會真正改變。我們可以通過監(jiān)聽這兩個(gè)事件,來控制何時(shí)觸發(fā)input事件。

          具體實(shí)現(xiàn)方式是,在監(jiān)聽到compositionstart事件時(shí),將輸入框的值存儲下來,然后在監(jiān)聽到compositionend事件時(shí),再將輸入框的值與之前存儲的值進(jìn)行比較,如果不同,則觸發(fā)自定義的input事件,并將新值作為參數(shù)傳遞給監(jiān)聽器。

          2、代碼實(shí)現(xiàn)

          (1)輸入框

          html復(fù)制代碼<div class="input-text-title">正常情況</div>
          <div class="input-text-content">{{ inputText }}</div>
          <input
              placeholder="請輸入"
              class="input-text"
              @input="doInput"
              id="inputContent"
          />

          簡單定義一個(gè)輸入框,監(jiān)聽其input事件,inputText保存實(shí)時(shí)輸入內(nèi)容并展示到頁面上。

          (2)監(jiān)聽compositionstart和compositionend事件

          javascript復(fù)制代碼const inputContent=document.getElementById("inputContent");
          inputContent.addEventListener("compositionstart", ()=> {
              this.isComposing=true;
              this.inputComplate(inputContent.value);
          });
          inputContent.addEventListener("compositionend", ()=> {
              this.isComposing=false;
              if (inputContent.value !==this.inputText) {
                  this.inputComplate(inputContent.value);
              }
          });

          首先,我們通過getElementById方法獲取到id為"inputContent"的輸入框元素,并將其賦值給inputContent常量。

          然后,我們給inputContent元素添加compositionstart事件的監(jiān)聽器。在事件觸發(fā)時(shí),會執(zhí)行回調(diào)函數(shù)。在回調(diào)函數(shù)中,我們將isComposing變量設(shè)置為true,表示正在進(jìn)行拼音輸入,然后調(diào)用inputComplate方法處理輸入框的值,并將輸入框的值作為參數(shù)傳遞給inputComplate方法。

          接下來,我們給inputContent元素添加compositionend事件的監(jiān)聽器。在事件觸發(fā)時(shí),同樣會執(zhí)行回調(diào)函數(shù)。在回調(diào)函數(shù)中,我們將isComposing變量設(shè)置為false,表示拼音輸入結(jié)束,然后同樣調(diào)用inputComplate方法處理輸入框的值,并將輸入框的值作為參數(shù)傳遞給inputComplate方法。

          通過監(jiān)聽這兩個(gè)事件,并在事件觸發(fā)時(shí)調(diào)用相應(yīng)的處理方法,我們可以實(shí)現(xiàn)在拼音輸入過程中控制input事件的觸發(fā)時(shí)機(jī),從而達(dá)到不觸發(fā)input事件的效果。

          (3)input事件判斷是否正在輸入拼音

          javascript復(fù)制代碼inputComplate(value) {
              this.inputText=value;
          },
          doInput(event) {
              if (this.isComposing) return;
              const value=event.target.value;
              this.inputComplate(value);
          },

          輸入框input事件綁定的是doInput方法,這個(gè)方法在這里只是用于過渡一下,在這里我們需要判斷當(dāng)前是否正在輸入拼音,如果是在輸入拼音的話我們就直接返回,不進(jìn)行后續(xù)操作,如果不是的話則調(diào)用inputComplate進(jìn)行后續(xù)處理,真正的處理邏輯應(yīng)該是在inputComplate方法中。

          這樣我們就簡單的完成了一個(gè)忽略拼音輸入過程中的input事件的功能

          本文到此結(jié)束

          且慢,雖然上面這樣操作之后可以得到一個(gè)可以忽略拼音輸入過程中的input事件的輸入框;但是,如果我們有很多個(gè)輸入框需要加上這個(gè)功能呢?這樣的話我們每寫一個(gè)input框,想要加上這個(gè)功能的話不還得加一堆亂七八糟的代碼來處理,這明顯很不合理。

          (4)封裝成一個(gè)vue指令

          javascript復(fù)制代碼export default {
              bind(el, binding) {
                  let isComposing=false;
                  let value="";
                  
                  el.addEventListener("compositionstart", ()=> {
                      isComposing=true;
                      value=el.value;
                  });
          
                  el.addEventListener("compositionend", ()=> {
                      isComposing=false;
                      if (value !==el.value) {
                          binding.value(el.value);
                      }
                  });
          
                  // 添加自定義的input事件監(jiān)聽器
                  el.addEventListener("input", (event)=> {
                      if (isComposing) {
                          return;
                      }
                      const value=event.target.value;
                      // 處理輸入框的值
                      binding.value(value);
                  });
              },
          };
          html復(fù)制代碼<input
              placeholder="輸入試試"
              class="input-text"
              v-JIgnorePinyin="doInput1"
          />

          在bind鉤子函數(shù)中,我們首先定義了兩個(gè)變量isComposing和value,分別用于記錄是否正在進(jìn)行拼音輸入和輸入框的值。

          然后,我們給輸入框元素el添加compositionstart事件的監(jiān)聽器。在事件觸發(fā)時(shí),將isComposing設(shè)置為true,表示正在進(jìn)行拼音輸入,并將輸入框的值賦給value。

          接下來,我們給輸入框元素el添加compositionend事件的監(jiān)聽器。在事件觸發(fā)時(shí),將isComposing設(shè)置為false,表示拼音輸入結(jié)束。然后,我們比較value和輸入框的當(dāng)前值el.value是否相等,如果不相等,則說明輸入框的值已經(jīng)發(fā)生了變化,此時(shí)我們調(diào)用binding.value方法,將當(dāng)前輸入框的值el.value作為參數(shù)傳遞給綁定該指令的處理函數(shù)。

          最后,我們給輸入框元素el添加input事件的監(jiān)聽器。在事件觸發(fā)時(shí),首先判斷isComposing的值,如果為true,則直接返回,不做任何處理。如果isComposing的值為false,說明拼音輸入已經(jīng)完成,此時(shí)我們獲取輸入框的值event.target.value,并將其作為參數(shù)調(diào)用binding.value方法,從而處理輸入框的值。

          通過定義這個(gè)自定義指令,我們可以在Vue組件中使用它來監(jiān)聽拼音輸入過程中的事件,并執(zhí)行相應(yīng)的處理邏輯,從而實(shí)現(xiàn)更加靈活的輸入框交互。

          這樣的話后面需要加功能只需要一個(gè)指令即可搞定。

          組件庫

          組件文檔

          目前該組件也已經(jīng)收錄到我的組件庫,組件文檔地址如下: jyeontu.xyz/jvuewheel/#…

          組件內(nèi)容

          組件庫中還有許多好玩有趣的組件,如:

          • 懸浮按鈕
          • 評論組件
          • 詞云
          • 瀑布流照片容器
          • 視頻動態(tài)封面
          • 3D輪播圖
          • web桌寵
          • 貢獻(xiàn)度面板
          • 拖拽上傳
          • 自動補(bǔ)全輸入框
          • 圖片滑塊驗(yàn)證
          等等……

          組件庫源碼

          組件庫已開源到gitee,有興趣的也可以到這里看看:gitee.com/zheng_yongt…

          覺得有幫助的可以點(diǎn)個(gè)star~

          有什么問題或錯(cuò)誤可以指出,歡迎pr~

          有什么想要實(shí)現(xiàn)的組件或想法可以聯(lián)系我~

          作者:JYeontu

          鏈接:https://juejin.cn/post/7330439494666223642

          開發(fā)過程中,基本都遇到過需要限制輸入的情況,比如金額、僅字母數(shù)字、可輸入小數(shù)位等,網(wǎng)上搜了很多方法也遇到一些坑,所以分享出來。

          1.使用修飾符實(shí)現(xiàn)數(shù)字輸入

          在VUE中可以在v-modal后添加修飾符的形式來限制輸入,比如:

          <input v-model.number="testValue" type="number">
          

          .number可以實(shí)現(xiàn)限制數(shù)字輸入,但是會有以下問題:

          • 會出現(xiàn)type="number"自帶樣式,當(dāng)然可以通過添加以下css清除
          /* 普通IE瀏覽器 樣式清除 */
          input::-webkit-outer-spin-button,input::-webkit-inner-spin-button{
          -webkit-appearance: none !important;
          }
          /* 火狐瀏覽器樣式清除 */
          input[type="number"]{
          -moz-appearance:textfield;
          }
          
          • 可以無限輸入特殊符號+-.,會導(dǎo)致清空data中的值testValue 這里的修飾符也無法實(shí)現(xiàn)定制限制輸入,不能滿足要求

          2.監(jiān)聽輸入框變化

          通過@input監(jiān)聽更新數(shù)據(jù),實(shí)現(xiàn)只能輸入數(shù)字,而且可以自行定制限制輸入內(nèi)容

          <input v-model="testValue" @input="testValue = testValue.replace(/[^\d]/g,'')">
          

          此方法可以滿足需求,但是無法封裝進(jìn)行批量使用

          3.封裝全局指令

          封裝input限制輸入指令

          //input.js
          
          const addListener = function(el, type, fn) {
            el.addEventListener(type, fn, false)
          }
          
          //去掉空格
          const spaceFilter = function(el) {
            addListener(el, 'input', () => {
              el.value = el.value.replace(/\s+/, '')
            })
          }
          
          // 限制只能輸入整數(shù)和小數(shù)(價(jià)格類、最多兩位小數(shù))
          const priceFilter = function(el) {
            addListener(el, 'input', () => {
              el.value = (el.value.match(/^\d*(\.?\d{0,2})/g)[0]) || null
              if (isNaN(el.value)) {
                el.value = ''
              }
            })
          }
          
          export default {
            bind(el, binding) {
              if (el.tagName.toLowerCase() !== 'input') {
                el = el.getElementsByTagName('input')[0]
              }
              spaceFilter(el)
              switch (binding.arg) {
                case 'price':
                  priceFilter(el)
                  break
                default:
                  console.warn('未知指令類型',binding.arg)
                  break
              }
            }
          }
          

          注冊全局自定義指令

          //main.js
          
          import inputFilter from '@/directives/InputFilter.js'
          
          Vue.directive('inputFilter', inputFilter)
          

          使用v-input-filter指令

          <input v-modal="testValue" v-input-filter:price>
          

          這樣封裝在使用時(shí)會出現(xiàn)一個(gè)隱蔽的bug,就是在輸入指令中正則限制以外的字符時(shí),視圖中輸入框顯示是正確的,但是在瀏覽器控制欄Vue Devtools中的testValue最后一位字符是最后輸入的時(shí)的字符。

          比如輸入abc、123abc輸入框內(nèi)是 、123,但實(shí)際testValue值是c、123c。

          原因是vue中綁定的值是通過監(jiān)聽input進(jìn)行賦值的,直接修改輸入框值不會觸發(fā)input事件,需要通過dispatchEvent再次手動觸發(fā)input事件,修改如下:

          //input.js
          
          ···
          
          // 防抖
          let debounce = (fn, delay) => {
            var delay = delay || 100;
            var timer;
            return function() {
              var th = this;
              var args = arguments;
              if (timer) {
                clearTimeout(timer);
              }
              timer = setTimeout(function() {
                timer = null;
                fn.apply(th, args);
              }, delay);
            };
          }
          
          ···
          
          // 限制只能輸入整數(shù)和小數(shù)(價(jià)格類、兩位小數(shù))
          const priceFilter = function(el) {
            addListener(el, 'input', debounce(() => {//添加防抖 防止反復(fù)觸發(fā)事件導(dǎo)致內(nèi)存溢出
              el.value = (el.value.match(/^\d*(\.?\d{0,2})/g)[0]) || null
              if (isNaN(el.value)) {
                el.value = ''
              }
              //觸發(fā)input事件
              el.dispatchEvent(new Event('input'))
            }))
          }
          
          ···
          

          到這里算是滿足了要求,也能方便的使用,分享出來希望能夠拋磚引玉,學(xué)習(xí)到更好的方式,如果有更好的方法請告訴我,謝謝!


          主站蜘蛛池模板: 中文字幕一区二区三区四区| AV天堂午夜精品一区二区三区| 国产成人精品一区二区三区无码| 国产精品亚洲一区二区麻豆| 欧洲精品免费一区二区三区| 精品不卡一区二区| 午夜福利一区二区三区在线观看| 国产日韩精品一区二区在线观看播放 | 无码人妻精品一区二区三区99仓本 | 亚洲天堂一区二区三区| 久久精品综合一区二区三区| 国产一区二区三区无码免费| 一区二区亚洲精品精华液| 亚洲电影一区二区三区| 国产一区二区福利| 国产成人无码精品一区在线观看| 国产大秀视频一区二区三区| 性色AV一区二区三区无码| 无码日韩精品一区二区免费| 伊人无码精品久久一区二区| 国产99久久精品一区二区| 国产91久久精品一区二区| 亚洲色无码专区一区| 激情无码亚洲一区二区三区| 精品深夜AV无码一区二区老年| 久久无码AV一区二区三区| 亚洲一区在线观看视频| 亚洲综合无码一区二区三区| 中文字幕乱码亚洲精品一区| 国产精品视频一区国模私拍| 极品少妇一区二区三区四区| 国产精品电影一区二区三区 | 亚洲区精品久久一区二区三区| 国产综合一区二区| 亚洲一区中文字幕久久| 日韩亚洲AV无码一区二区不卡 | 精品一区二区三区视频在线观看 | 国产伦精品一区二区| 一区二区三区免费看| 国产精品va一区二区三区| 国产成人无码精品一区在线观看|