可能你會對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這個庫作得真的很細緻。