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

posted @ 2022-04-06 17:08  吴小明-  阅读(488)  评论(0编辑  收藏  举报