你知道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这个库作得真的很细致。

相关文章
相关标签/搜索