admin管理员组文章数量:1277394
I have this component code originally written in Vue 2 using the options API that is now being migrated to Vue 3. The code was simplified to the following where items
are added/removed from the array and then the watcher is called to do other things (in this case just console.log
):
<template>
<button @click="addItem">Add</button>
<button @click="removeItem">Remove</button>
<br><br>
<div>Items:</div>
<div v-for="item in items">{{item}}</div>
</template>
<script>
export default {
data() {
return {
items: [],
};
},
watch: {
items: {
handler() {
console.log('items', this.items);
},
//deep: true
}
},
methods: {
addItem() {
this.items.push({i: this.items.length});
},
removeItem() {
this.items.pop();
}
}
};
</script>
This worked fine in Vue 2 where the items
watcher would fire each time an item is added/removed from the array. My actual object has far more attributes on it than just i
, so if I mark the watcher with deep: true
, the watcher fires as expected, but the view becomes unusably slow. How can I make this array.
I noticed if I change the addItem
method to this.items = [...this.items, {i: this.items.length}];
, then the watcher gets called as I would expect, but this also seems really inefficient since you're creating a new array each time. Is there another way to get the watcher to run only on push
/pop
/unshift
/shift
/splice
calls that modify the existing array's structure without having to reassign the array reference or mark the array as deep
?
I have this component code originally written in Vue 2 using the options API that is now being migrated to Vue 3. The code was simplified to the following where items
are added/removed from the array and then the watcher is called to do other things (in this case just console.log
):
<template>
<button @click="addItem">Add</button>
<button @click="removeItem">Remove</button>
<br><br>
<div>Items:</div>
<div v-for="item in items">{{item}}</div>
</template>
<script>
export default {
data() {
return {
items: [],
};
},
watch: {
items: {
handler() {
console.log('items', this.items);
},
//deep: true
}
},
methods: {
addItem() {
this.items.push({i: this.items.length});
},
removeItem() {
this.items.pop();
}
}
};
</script>
This worked fine in Vue 2 where the items
watcher would fire each time an item is added/removed from the array. My actual object has far more attributes on it than just i
, so if I mark the watcher with deep: true
, the watcher fires as expected, but the view becomes unusably slow. How can I make this array.
I noticed if I change the addItem
method to this.items = [...this.items, {i: this.items.length}];
, then the watcher gets called as I would expect, but this also seems really inefficient since you're creating a new array each time. Is there another way to get the watcher to run only on push
/pop
/unshift
/shift
/splice
calls that modify the existing array's structure without having to reassign the array reference or mark the array as deep
?
2 Answers
Reset to default 2Turns out as of Vue 3.5+, this can be fixed with deep watchers by marking the watcher with deep
and then the level of depth to watch (in this case 1
). So the watcher code becomes:
watch: {
items: {
handler() {
console.log('items', this.items);
},
deep: 1
}
},
This ensures the array watcher is called on updates to the structure of the array, but not deeply nested changes to objects within the array (much like how it worked in Vue 2).
The answer is the correct way to do this in Vue 3.5 and later. Prior to 3.5, this required an array to be iterated, which still may be much less expensive performance-wise than deep watcher:
created() {
this.$watch(() => [...this.items], () => {
console.log('items', this.items);
});
}
本文标签:
版权声明:本文标题:javascript - In Vue 3, how can I watch changes to the array structure without marking it as `deep` and having every nested level 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1741252067a2365978.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论