Hi, I’m Daotin, front end team leader. If you want to get more front end highlights, follow me and unlock new front end growth poses.

Recent hot articles:

  • Waterfall flow, it’s so easy
  • Four common ajax cross-domain solutions (easy to understand)
  • Vue. Js Naming Style Guide (Easy to remember Version)

The following text:

demand

Recently there was a requirement for list filtering based on input text. This is a very common requirement. So the approximate code is as follows:

<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: [
        "Love and Hope."."Flowers"."Mojito"."The Longest Movie ever."."Grandpa's tea."]}; },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>
Copy the code

Listen for input events in the input box, and then trigger changes to the filteredList list.

Everything is so natural.

However, when we input Chinese, the pinyin will be displayed first, resulting in the process of input Chinese, the triggered filter list is empty, and the result will be displayed only when the Chinese is displayed.

Compositionstart and compositionend

So there are two events, compositionStart and CompositionEnd

MDN: developer.mozilla.org/zh-CN/docs/…

The compositionStart event is triggered when the user starts typing Chinese characters using the pinyin input method. The comPositionEnd event is emitted when the composition of a text paragraph is complete or cancelled.

In other words, the compositionStart event will be triggered when we start typing Chinese, and the CompositionStart event will not be triggered during the Chinese input process, and the ComPOSItionEnd event will be triggered when we finish typing Chinese.

In addition, it is found that compositionStart is triggered before the input event when entering Chinese.

So that’s all I need to do, so I’ll just say lock, when compositionStart fires, lock=true, when compositionEnd fires, lock=false. Filtering in input events is performed only when lock is false.

The code becomes the following:

<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: [
        "Love and Hope."."Flowers"."Mojito"."The Longest Movie ever."."Grandpa's tea."], the lock;false./ / marking
    };
  },
  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>
Copy the code

V – form of the model

In the code above, we are not using vue’s V-Model two-way binding. If you use v-Model, you will find that the input event is not triggered while typing Chinese.

View the source of vue SRC/platforms/web/runtime/directives/model. The js, there are so few lines of code:

export default {
  inserted (el, binding, vnode) {
    if (vnode.tag === 'select') {
      setSelected(el, binding, vnode.context)
      el._vOptions = [].map.call(el.options, getValue)
    } else if (vnode.tag === 'textarea' || isTextInputType(el.type)) {
      el._vModifiers = binding.modifiers
      if(! binding.modifiers.lazy) {// Safari < 10.2&uiWebView doesn't fire compositionEnd When
        // switching focus before confirming composition choice
        // this also fixes the issue where some browsers e.g. iOS Chrome
        // fires "change" instead of "input" on autocomplete.
        el.addEventListener('change', onCompositionEnd)
        if(! isAndroid) { el.addEventListener('compositionstart', onCompositionStart)
          el.addEventListener('compositionend', onCompositionEnd)
        }
        /* istanbul ignore if */
        if (isIE9) {
          el.vmodel = true
        }
      }
    }
  }
}

/ /...

function onCompositionStart (e) {
  e.target.composing = true
}

function onCompositionEnd (e) {
  // prevent triggering an input event for no reason
  if(! e.target.composing)return
  e.target.composing = false
  trigger(e.target, 'input')}function trigger (el, type) {
  const e = document.createEvent('HTMLEvents')
  e.initEvent(type, true.true)
  el.dispatchEvent(e)
}
Copy the code

It can be found that VUE has already done the same operation, so V-Model helped us to do a lot of optimization, which is also one of the reasons why VUE is so good.


For more exciting content, follow me to get more front-end technology and personal growth related content, I believe interesting people will meet eventually!

It is said that those who give a “like” will be lucky enough to get a promotion and a raise a month later