input 輸入控制-原生和vue的指令方式

我們經(jīng)常會要求用戶在文本框中輸入特定的數(shù)據(jù),或者輸入特定格式的數(shù)據(jù).例如,必須包含木屑字符,或者必須匹配某種模式.由于文本框在默認(rèn)情況下沒有提供多少驗(yàn)證數(shù)據(jù)的手段,因此必須是喲個(gè)JavaScript來完成此類過濾輸入的操作.而綜合運(yùn)用事件和DOM手段,就可以將普通的文本框轉(zhuǎn)換成能夠理解用戶輸入數(shù)據(jù)的工程型控件.
1.原生事件方法:

  • input事件操作el.value值
    此處按照事件的順序均可實(shí)現(xiàn)
<!--onkeydown-->
 <input onkeydown="this.value=this.value.replace(/\D/g,'')">
<!--onkeypress-->
 <input onkeypress="this.value=this.value.replace(/\D/g,'')">
<!--推薦-->
<!--onkeyup-->
 <input onkeyup="this.value=this.value.replace(/\D/g,'')">

onkeydown,onkeypress都有一個(gè)比較明顯的缺點(diǎn),就是非數(shù)組字符仍可以輸入,只是在下一次輸入之后才會替換掉.
keyup事件能在輸入不正確的字符之后立刻就能清除掉, 但是這個(gè)動(dòng)作還是人眼可見的.

封裝 : 此種方式也可先定義一個(gè)函數(shù),將this傳遞到該函數(shù)然后進(jìn)行復(fù)雜操作

<input onkeyup="keyUp(this)">
<script>
function keyUp(el) {
  el.value = el.value.replace(/\D/g, '');
}
</script>
  • 最佳方案 event.preventDefault
    為了讓不希望輸入的字符不會在input框中閃現(xiàn),可以通過阻止某個(gè)按鍵的默認(rèn)行為來屏蔽此類字符.在極端的情況下,可以通過下列代碼屏蔽所有按鍵操作.
EventUtil.addHandler(textBox,"keypress",function(event){
    event=EventUtil.getEvent(event);
    EventUtil.preventDefault(event);
})

放上用到的EventUtil公共方法

let EventUtil = {
  addHandler: function (element, type, handler) {
    if (element.addEventListener) {
      element.addEventListener(type, handler, false);
    } else if (element.attachEvent) {
      element.attachEvent("on" + type, hander);
    } else {
      element["on" + type] = handler;
    }
  },
  removeHandler: function (element, type, handler) {
    if (element.removeEventListener) {
      element.removeEventListener(type, handler, false);
    } else if (element.detachEvent) {
      element.detachEvent("on" + type, handler);
    } else {
      element["on" + type] = null;
    }
  },
  getEvent: function (event) {
    return event ? event : window.event;
  },
  getTarget: function (event) {
    return event.target || event.srcElement;
  },
  preventDefault: function (event) {
    if (event.preventDefault) {
      event.preventDefault();
    } else {
      event.returnValue = false;
    }
  },
  stopPropagation: function (event) {
    if (event.stopPropagation) {
      event.stopPropagation();
    } else {
      event.cancelBubble = true;
    }
  },
  getCharCode: function (event) {
    if (typeof event.charCode === "number") {
      return event.charCode;
    } else {
      return event.keyCode;
    }
  }, 
  getClipboardText: function (event) {
    var clipboardData = (event.clipboardData || window.clipboardData);
    return clipboardData.getData("text");
  },
  setClipboardText: function (event, value) {
    if (event.clipboardData) {
      return event.clipboardData.setData("text/plain", value);
    } else if (window.clipboardData) {
      return window.clipboardData.setData("text", value);
    }
  }
}

運(yùn)行以上代碼后,由于所有按鍵操作都被屏蔽,結(jié)果會導(dǎo)致文本框變成只讀的.如果只想屏蔽特定的字符,則需要檢測keypress事件對應(yīng)的字符編碼,然后再?zèng)Q定如何響應(yīng).例如,下列代碼只允許用戶輸入數(shù)值.

<input type="text" id="textBox">
<script>
EventUtil.addHandler(textBox, "keypress", function (event) {
  event = EventUtil.getEvent(event);
  var target = EventUtil.getTarget(event);
  var charCode = EventUtil.getCharCode(event);
  if (!/\d/.test(String.fromCharCode(charCode)) && charCode>9 && !event.ctrlKey) {
    EventUtil.preventDefault(event);
  }
})
</script>

例子中,使用EventUtil.getCharCode()實(shí)現(xiàn)了跨瀏覽器取得字符編碼,然后使用String.fromCharCode()將字符編碼轉(zhuǎn)換成字符串,再使用正則表達(dá)式/\d/來測試該字符串,將測試失敗的數(shù)值使用EventUtil.preventDefault()屏蔽按鍵事件.

  1. vue指令方式
    通過vue指令可以在input 標(biāo)簽上添加相應(yīng)指令名稱就可以達(dá)到操作原生input事件,滿足各種input功能需求, 邏輯即清晰亦是解耦,可移植性強(qiáng).
  • 限制input輸入數(shù)字最大最小值
    下面是我封裝后的完整示例:
    HTML部分
<div id="app">
      <h2>input 控制輸入</h2>
      <div>
        <input type="number" v-model.lazy="value" v-int-num="{cb:showAlert,min:10,max:100,decimal:0}" >
      </div>
</div>

JavaScript部分

// 截取精確小數(shù)方法
const round = (n, decimals = 0) => Number(`${Math.round(`${n}e${decimals}`)}e-${decimals}`);
Vue.directive('int-num', {
  bind: function (el, binding, vnode) {
    let {
      cb,//回調(diào)函數(shù),可在不滿足條件的情況下做一下后續(xù)提示等操作
      min,//最小值
      max,//最大值
      decimal //精確小數(shù)位數(shù)
    } = binding.value ? binding.value : {
      cb: Function,
      min: 0,
      max: 100,
      decimal: 0
    };

    if (min > max) {
      throw new Error("最小值不能大于最大值");
      return;
    }

    el.keypressHandler = function (event) {
      // 當(dāng)小數(shù)位數(shù)位0時(shí),此時(shí)不允許輸入'.'點(diǎn)符號
      if (decimal === 0 && event.charCode === 46) {
        event.preventDefault();//組織默認(rèn)行為
        event.stopPropagation();//停止傳遞冒泡事件,不會進(jìn)入input事件中
      }
    }
    el.inputHandler = function (event) {
      if (isNaN(Number(el.value))) {
        el.value = "";
      } else {
        el.value = round(Number(el.value), decimal);
      }
      cb.call(null, Number(el.value));
      if (el.value > max) {
        el.value = max;
      }
    }
    el.blurHandler = function () {
      if (el.value > max) {
        cb.call(this, "最大值是 " + max)
      }
      if (el.value < min) {
        cb.call(this, "最小值是 " + min);
      }
    }
    // 添加事件監(jiān)聽
    el.addEventListener("keypress", el.keypressHandler)
    el.addEventListener('input', el.inputHandler);
    el.addEventListener("blur", el.blurHandler);
  },
  unbind: function (el) {
    // 移除事件監(jiān)聽
    el.removeEventListener("keypress", el.keypressHandler)
    el.removeEventListener('input', el.inputHandler);
    el.removeEventListener("blur", el.blurHandler);
  }
});
new Vue({
  el: "#app",
  data: {
    value: ""
  },
  methods: {
    showAlert(e) {
      console.info(JSON.stringify(e));
    }
  }
})

特別注意:
v-model值綁定的時(shí)候需要使用.lazy進(jìn)行修飾,因?yàn)?code>v-model內(nèi)部也是用input事件截取值和綁定值的渗蟹,哪個(gè)先執(zhí)行是不確定的芹彬,偶爾會看到input值閃動(dòng)出現(xiàn)减江。當(dāng)用.lazy修飾之后速缨,v-model內(nèi)部使用change事件綁定值尤慰,而change事件是在input事件之后关斜,故此時(shí)已經(jīng)是經(jīng)過自定義處理之后的值叽粹,不會出現(xiàn)數(shù)值跳動(dòng)的情況炭菌。

其實(shí)內(nèi)部實(shí)現(xiàn)也是input事件的原生方法,經(jīng)過vue指令的封裝,控制輸入行為會更靈活,也更直觀和方便.
如果需要對特定字符進(jìn)行組織或只允許輸入特定字符,可以在keypress事件中用 event.charCode判斷即可實(shí)現(xiàn).

題外話:
為了只允許輸入數(shù)字可以用input[type=number]和input[type=tel],但是有一些缺陷

  • input[type=number]
    不支持maxlength罪佳,支持輸入e,.
  • input[type=tel]
    在移動(dòng)設(shè)備上,input[type=tel] 是支持maxlength的黑低,而且只能輸入數(shù)字鍵盤赘艳。支持輸入#,*,+
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市克握,隨后出現(xiàn)的幾起案子蕾管,更是在濱河造成了極大的恐慌,老刑警劉巖菩暗,帶你破解...
    沈念sama閱讀 217,826評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件娇掏,死亡現(xiàn)場離奇詭異,居然都是意外死亡勋眯,警方通過查閱死者的電腦和手機(jī)婴梧,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,968評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來客蹋,“玉大人塞蹭,你說我怎么就攤上這事⊙扰鳎” “怎么了番电?”我有些...
    開封第一講書人閱讀 164,234評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我漱办,道長这刷,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,562評論 1 293
  • 正文 為了忘掉前任娩井,我火速辦了婚禮暇屋,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘洞辣。我一直安慰自己咐刨,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,611評論 6 392
  • 文/花漫 我一把揭開白布扬霜。 她就那樣靜靜地躺著定鸟,像睡著了一般。 火紅的嫁衣襯著肌膚如雪著瓶。 梳的紋絲不亂的頭發(fā)上联予,一...
    開封第一講書人閱讀 51,482評論 1 302
  • 那天,我揣著相機(jī)與錄音材原,去河邊找鬼躯泰。 笑死,一個(gè)胖子當(dāng)著我的面吹牛华糖,可吹牛的內(nèi)容都是我干的麦向。 我是一名探鬼主播,決...
    沈念sama閱讀 40,271評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼客叉,長吁一口氣:“原來是場噩夢啊……” “哼诵竭!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起兼搏,我...
    開封第一講書人閱讀 39,166評論 0 276
  • 序言:老撾萬榮一對情侶失蹤卵慰,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后佛呻,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體裳朋,經(jīng)...
    沈念sama閱讀 45,608評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,814評論 3 336
  • 正文 我和宋清朗相戀三年吓著,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了鲤嫡。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,926評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡绑莺,死狀恐怖暖眼,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情纺裁,我是刑警寧澤诫肠,帶...
    沈念sama閱讀 35,644評論 5 346
  • 正文 年R本政府宣布司澎,位于F島的核電站,受9級特大地震影響栋豫,放射性物質(zhì)發(fā)生泄漏挤安。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,249評論 3 329
  • 文/蒙蒙 一丧鸯、第九天 我趴在偏房一處隱蔽的房頂上張望蛤铜。 院中可真熱鬧,春花似錦骡送、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,866評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至怨愤,卻和暖如春派敷,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背撰洗。 一陣腳步聲響...
    開封第一講書人閱讀 32,991評論 1 269
  • 我被黑心中介騙來泰國打工篮愉, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人差导。 一個(gè)月前我還...
    沈念sama閱讀 48,063評論 3 370
  • 正文 我出身青樓试躏,卻偏偏與公主長得像,于是被迫代替她去往敵國和親设褐。 傳聞我的和親對象是個(gè)殘疾皇子颠蕴,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,871評論 2 354

推薦閱讀更多精彩內(nèi)容

  • ??JavaScript 與 HTML 之間的交互是通過事件實(shí)現(xiàn)的犀被。 ??事件,就是文檔或?yàn)g覽器窗口中發(fā)生的一些特...
    霜天曉閱讀 3,490評論 1 11
  • ??JavaScript 最初的一個(gè)應(yīng)用,就是分擔(dān)服務(wù)器處理表單的責(zé)任雪隧,打破處處依賴服務(wù)器的局面西轩。 ??盡管目前的...
    霜天曉閱讀 668評論 0 3
  • 表單基礎(chǔ)知識 在HTML中,表單是由 元素來表示的脑沿,而在JS中遭商,表單對應(yīng)的則是HTMLFormElement類型。...
    oWSQo閱讀 909評論 0 1
  • 第3章 基本概念 3.1 語法 3.2 關(guān)鍵字和保留字 3.3 變量 3.4 數(shù)據(jù)類型 5種簡單數(shù)據(jù)類型:Unde...
    RickCole閱讀 5,126評論 0 21
  • 官網(wǎng) 中文版本 好的網(wǎng)站 Content-type: text/htmlBASH Section: User ...
    不排版閱讀 4,381評論 0 5