SoFunction
Updated on 2025-04-06

Detailed explanation of the API that is easy to ignore

nextTick

nextTick is a function provided by , not built in the browser. The nextTick function receives a callback function cb, which is executed after the next DOM update loop. For example, the following example:

<template>
  <div>
    <p v-if="show" ref="node">content</p>
    <button @click="handleShow">show</button>
  </div>
</template>
<script>
  export default {
    data () {
      return {
        show: false
      }
    },
    methods: {
      handleShow () {
         = true;
        (this.$);  // undefined
        this.$nextTick(() => {
          (this.$);  // <p>Content</p>        });
      }
    }
  }
&lt;/script&gt;

When show is set to true, the p node has not been rendered yet, so the undefined printout is undefined, and in the nextTick callback, p has been rendered, and the node can be printed correctly.

The source code of nextTick is/vuejs/vue/b…, we can see that three methods: Promise, setTimeout and setImmediate are used to implement nextTick, and different methods will be used in different environments.

v-model syntax sugar

v-model is often used for two-way binding of data on form elements, such as <input>. In addition to native elements, it can also be used in custom components.

v-model is a syntactic sugar that can be broken down into props: value and events: input. That is to say, the component must provide a prop named value and a custom event named input. If these two conditions are met, the user can use v-model on the custom component. For example, the following example implements a numeric selector:

&lt;template&gt;
  &lt;div&gt;
    &lt;button @click="increase(-1)"&gt;reduce 1&lt;/button&gt;
    &lt;span style="color: red;padding: 6px"&gt;{{ currentValue }}&lt;/span&gt;
    &lt;button @click="increase(1)"&gt;add 1&lt;/button&gt;
  &lt;/div&gt;
&lt;/template&gt;
&lt;script&gt;
  export default {
    name: 'InputNumber',
    props: {
      value: {
        type: Number
      }
    },
    data () {
      return {
        currentValue: 
      }
    },
    watch: {
      value (val) {
         = val;
      }
    },
    methods: {
      increase (val) {
         += val;
        this.$emit('input', );
      }
    }
  }
&lt;/script&gt;

props cannot generally be modified within the component. It is modified through the parent. Therefore, the implementation of v-model generally has an internal data of currentValue. The value is obtained from the value at the beginning. When the value is modified, it is also updated in time through watch. The component will not modify the value of the value, but modify the currentValue. At the same time, the modified value is distributed to the parent component through a custom event input. After the parent component receives it, the parent component will modify the value. Therefore, the above number selector component can be used in the following two ways:

<template>
  <InputNumber v-model="value" />
</template>
<script>
  import InputNumber from '../components/input-number/';

  export default {
    components: { InputNumber },
    data () {
      return {
        value: 1
      }
    }
  }
</script>

or:

<template>
  <InputNumber :value="value" @input="handleChange" />
</template>
<script>
  import InputNumber from '../components/input-number/';

  export default {
    components: { InputNumber },
    data () {
      return {
        value: 1
      }
    },
    methods: {
      handleChange (val) {
         = val;
      }
    }
  }
</script>

If you don't want to use the two names value and input, starting from version 2.2.0, it provides a model option to specify their names, so the number selector component can also be written like this:

&lt;template&gt;
  &lt;div&gt;
    &lt;button @click="increase(-1)"&gt;reduce 1&lt;/button&gt;
    &lt;span style="color: red;padding: 6px"&gt;{{ currentValue }}&lt;/span&gt;
    &lt;button @click="increase(1)"&gt;add 1&lt;/button&gt;
  &lt;/div&gt;
&lt;/template&gt;
&lt;script&gt;
  export default {
    name: 'InputNumber',
    props: {
      number: {
        type: Number
      }
    },
    model: {
      prop: 'number',
      event: 'change'
    },
    data () {
      return {
        currentValue: 
      }
    },
    watch: {
      value (val) {
         = val;
      }
    },
    methods: {
      increase (val) {
         += val;
        this.$emit('number', );
      }
    }
  }
&lt;/script&gt;

In the model option, you can specify the names of prop and event, instead of having to use value and input, because these two names have other uses in some native form elements.

.sync modifier

If you have used it, you must be familiar with .sync. In , you can use .sync to bind data in two-way, that is, both the parent component or the child component can modify this data, and it is a bidirectional response. This usage is discarded in the purpose of decoupling the parent and child components as much as possible to avoid the child components inadvertently modifying the state of the parent components.

However, in version 2.3.0, the .sync modifier was added, but its usage is not exactly the same as . The .sync is not a real two-way binding, but a syntax sugar. Modification of data is still done in the parent component, not in the child component.

It's still an example of a number selector. This time, instead of using v-model, it uses .sync, which can be rewritten like this:

&lt;template&gt;
  &lt;div&gt;
    &lt;button @click="increase(-1)"&gt;reduce 1&lt;/button&gt;
    &lt;span style="color: red;padding: 6px"&gt;{{ value }}&lt;/span&gt;
    &lt;button @click="increase(1)"&gt;add 1&lt;/button&gt;
  &lt;/div&gt;
&lt;/template&gt;
&lt;script&gt;
  export default {
    name: 'InputNumber',
    props: {
      value: {
        type: Number
      }
    },
    methods: {
      increase (val) {
        this.$emit('update:value',  + val);
      }
    }
  }
&lt;/script&gt;

Use cases:

<template>
  <InputNumber :="value" />
</template>
<script>
  import InputNumber from '../components/input-number/';

  export default {
    components: { InputNumber },
    data () {
      return {
        value: 1
      }
    }
  }
</script>

It looks much simpler than the implementation of v-model, and the implementation effect is the same. v-model can only have one in a component, but .sync can set many. Although .sync is good, it also has limitations, such as:

  • Cannot be used with expressions (such as v-bind:=" + '!'" is invalid);
  • It cannot be used on literal objects (such as ="{ title: }" will not work properly).

$set

$set has been introduced in the previous section, and there are two situations that will be used:

Due to JavaScript limitations, Vue cannot detect arrays with the following changes:

  • When setting an item directly using the index, for example: [index] = value;
  • When modifying the length of the array, for example: = newLength.

Due to JavaScript limitations, Vue cannot detect the addition or removal of object properties.

For example, it is:

// Arrayexport default {
  data () {
    return {
      items: ['a', 'b', 'c']
    }
  },
  methods: {
    handler () {
      [1] = 'x';  // Not responsive    }
  }
}

Use $set:

// Arrayexport default {
  data () {
    return {
      items: ['a', 'b', 'c']
    }
  },
  methods: {
    handler () {
      this.$set(, 1, 'x');  // is responsive    }
  }
}

Take the object as an example:

// Objectexport default {
  data () {
    return {
      item: {
        a: 1
      }
    }
  },
  methods: {
    handler () {
       = 2;  // Not responsive    }
  }
}

Use $set:

// Objectexport default {
  data () {
    return {
      item: {
        a: 1
      }
    }
  },
  methods: {
    handler () {
      this.$set(, 'b', 2);  // is responsive    }
  }
}

In addition, the following methods of arrays can trigger view updates, that is, responsive:

push()、pop()、shift()、unshift()、splice()、sort()、reverse()。

There is another trick, which is to copy an array first, then modify it through index, and then replace the original array entirely, such as:

handler () {
  const data = [...];
  data[1] = 'x';
   = data;
}

Compute attribute set

Computed attributes are simple and can also be used in large quantities, but most of the time, we just use its default get method, which is the usual writing method, to obtain data that depends on other states through computed. for example:

computed: {
  fullName () {
    return `${} ${}`;
  }
}

The fullName here can actually be written as an Object, not a Function, but the Function form is the get method we use by default. When written as Object, it can also use its set method:

computed: {
  fullName: {
    get () {
      return `${} ${}`;
    },
    set (val) {
      const names = (' ');
       = names[0];
       = names[ - 1];
    }
  }
}

Most of the time, the computed attribute is just for reading. After using set, it can be written. For example, if you execute = 'Aresn Liang', the computed set will be called, and the firstName and lastName will be assigned as Aresn and Liang.

Summarize

This is the end of this article about APIs that are easy to ignore. For more API content that is easy to ignore, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!