你知道compositionstart和compositionend嗎

可能你會對compositionstart和compositionend感到陌生,甚至重來沒據說過。但在特定場景下,這兩個事件十分有用。javascript

需求

最近接到一個需求,須要根據用戶輸入的文字來過濾列表選項。easy,一頓操做以後,代碼以下:vue

<template>
  <div id="app"> <input type="text" :value="filterText" @input="onInput" /> <ul> <li v-for="item in filteredList" :key="item"> {{ item }} </li> </ul> </div> </template>

<script>
export default {
  name: "app",
  data() {
    return {
      filterText: "",
      list: [
        "The Wealth of Nations",
        "戰爭與和平",
        "海底兩萬裏",
        "三國演義",
        "嫌疑人X的獻身"
      ]
    };
  },
  computed: {
    filteredList() {
      if (!this.filterText) {
        return this.list;
      }
      return this.list.filter(item => item.indexOf(this.filterText) > -1);
    }
  },
  methods: {
    onInput(e) {
      this.filterText = e.target.value;
    }
  }
};
</script>
複製代碼

效果以下圖:java

這時,我想過濾出帶有「三國」兩字的書名。咦,不對勁,我剛輸入拼音的s,就觸發了過濾。但是我想輸入中文呀,這效果顯然不是咱們想要的。web

分析

致使以上效果的緣由是input事件沒辦法知道咱們在使用中文輸入法,一旦輸入就修改filterText。那怎麼辦呢?session

compositionstart和compositionend

MDN是這麼解釋的:app

The compositionstart event is fired when a text composition system such as an input method editor starts a new composition session.For example, this event could be fired after a user starts entering a Chinese character using a Pinyin IME.this

The compositionend event is fired when a text composition system such as an input method editor completes or cancels the current composition session.For example, this event could be fired after a user finishes entering a Chinese character using a Pinyin IME.spa

也就是說,利用compositionstart和compositionend能夠知道中文輸入何時開始和結束。code

代碼修改成:orm

<template>
  <div id="app"> <input type="text" :value="filterText" @input="onInput" @compositionstart="onCompositionStart" @compositionend="onCompositionEnd" /> <ul> <li v-for="item in filteredList" :key="item"> {{ item }} </li> </ul> </div> </template>

<script>
export default {
  name: "app",
  data() {
    return {
      filterText: "",
      list: [
        "The Wealth of Nations",
        "戰爭與和平",
        "海底兩萬裏",
        "三國演義",
        "嫌疑人X的獻身"
      ],
      lock: false
    };
  },
  computed: {
    filteredList() {
      if (!this.filterText) {
        return this.list;
      }
      return this.list.filter(item => item.indexOf(this.filterText) > -1);
    }
  },
  methods: {
    onInput(e) {
      if (!this.lock) {
        this.filterText = e.target.value;
      }
    },
    onCompositionStart() {
      this.lock = true;
    },
    onCompositionEnd(e) {
      this.filterText = e.data;
      this.lock = false;
    }
  }
};
</script>
複製代碼

由於任何輸入都會觸發input,而輸入中文的時候才觸發compositionstartcompositionend,因此經過用一個標記lock來避免中文輸入過程當中觸發過濾。

最終效果:

v-model

你可能會發現,使用v-model不會出現文章開頭說的中文輸入時的過濾問題。查看vue的源碼src/platforms/web/runtime/directives/model.js,有這麼幾行代碼:

如今就很清楚了,原來v-model也作了相似的事情。不得不說vue這個庫作得真的很細緻。

相關文章
相關標籤/搜索