compositionstart和compositionend事件
使用场景:
input事件没办法知道我们在使用中文输入法,所以当我们在输入框中编辑中文的时候,按下字母的那一刻就开始触发input事件。
使用compositionstart和compositionend可以对此情况进行优化
需求:
根据用户输入的文字过滤列表选项
实现:
<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: [ 'hello world', '战争与和平', '海底两万里', '三国演义', '嫌疑人X的献身' ] } }, computed: { filteredList() { const { list, filterText } = this if (!filterText) return list return list.filter((item) => item.includes(filterText)) } }, methods: { onInput(e) { this.filterText = e.target.value }, onCompositionStart() { this.lock = true }, onCompositionEnd(e) { this.filterText = e.data this.lock = false } } } </script>
效果:
如果要搜索“三国”,在打出s时input事件就已经执行,但此时并不需要执行过滤
优化后如下:
<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: [ 'hello world', '战争与和平', '海底两万里', '三国演义', '嫌疑人X的献身' ], lock: false } }, computed: { filteredList() { const { list, filterText } = this if (!filterText) return list return list.filter((item) => item.includes(filterText)) } }, 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>
最终效果:
扩展:
如果使用v-model,没有中文过滤的问题,v-model内部已经使用compositionstart和compositionend处理过了
<template> <div id="app"> <!-- <input type="text" :value="filterText" @input="onInput"/> --> <input type="text" v-model="filterText" /> <ul> <li v-for="item in filteredList" :key="item">{{ item }}</li> </ul> </div> </template> <script> export default { name: 'app', data() { return { filterText: '', list: [ 'hello world', '战争与和平', '海底两万里', '三国演义', '嫌疑人X的献身' ] } }, computed: { filteredList() { const { list, filterText } = this if (!filterText) return list return list.filter((item) => item.includes(filterText)) } } } </script>
v-model相关源码:
参考:https://juejin.cn/post/6844903950634713096