可能你会对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
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,而输入中文的时候才触发compositionstart
和compositionend
,因此经过用一个标记lock
来避免中文输入过程当中触发过滤。
最终效果:
你可能会发现,使用v-model不会出现文章开头说的中文输入时的过滤问题。查看vue的源码src/platforms/web/runtime/directives/model.js,有这么几行代码:
如今就很清楚了,原来v-model也作了相似的事情。不得不说vue这个库作得真的很细致。