[Vuejs]-V-model on input change is heavy on performance

0👍

Try using .lazy modifier to sync after change events.

<input v-model.lazy="data"></input>

https://v2.vuejs.org/v2/guide/forms.html#lazy

EDIT

@IVO GELOV is right, when a component changes, this re-render. The solution is split your component into several child components.

https://v2.vuejs.org/v2/guide/reactivity.html

This is a code using slots to make it look like your example.

HTML

    <div id="app">
   <new-component>
     <ul>
       <li v-for="item in items" :key="item">
         {{ item.message }}
       </li>       
     </ul>    
   </new-component>
</div>

Javascript

    Vue.component('new-component', {
  data: () => {
    return {
      data: ''
    }
  },
  template: `
    <div>
      <div>{{ data }}</div>
      <slot></slot>
      <input v-model="data"></input>
    </div>`
})

new Vue({
        el: '#app',
        data: () => ({            
            items: [{
                    message: 'Foo'
                },
                {
                    message: 'Bar'
                }
            ]
        })
    })

0👍

Here’s a codepen showing the inner loop in its own component

Codepen.io

I’ve added Date.now() after items[x].message list items to show when the list is being rerendered.

In case codepen ever goes down:

<html>
<head>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script>
</head>
<body>
    <div id="app">
        Main vue: {{data}}
        <loop-component :data="loopdata"></loop-component>
        <input v-model="data"></input>
        <input v-model="loopdata"></input>
    </div>
<script>
Vue.component('loop-component', {
    props: ['data'],
    data() {
        return {
            items: [
                {message: 'Foo'},
                {message: 'Bar'}
            ]
        }
    },
    template: `
<div>
Loop component: {{ data }}
<ul>
  <li v-for="(item, index) in items" :key="index">
    {{ item.message + ' Date.now(): ' + Date.now() }}
  </li>
</ul>
</div>
`
});

let app = new Vue({
    el: '#app',
    data: () => ({
        data: '',
        'loopdata': '',
        items: [
            {message: 'Foo'},
            {message: 'Bar'},
        ]
    }),
});
</script>
</body>
</html>

-1👍

Since Vue 2.0+ whenever a change is detected – the whole component is re-rendered. If you want to avoid that – split your component into several child components.

Your example does not prove your point – the fact that there is a warning about duplicate keys inside the v-for does not mean that v-for is re-evaluated on each keypress. To confirm my statement – just change your code like this:

<li v-for="(item,idx) in items" :key="idx">

Now there is no warning.

Leave a comment