While porting an existing application from Vue2 to Vue3, I encountered a surprising problem.
How to let Vue3 monitor changes in "external" arrays?
This worked fine in Vue2, but stopped working in Vue3:
<ul id="list"> <li v-for="t in dataArray"> {{t}} </li> </ul> <script> var numbers = [1,2,3]; //this is my external array var app = Vue.createApp({ data() { return { dataArray : numbers } } //bind Vue to my external array }).mount("#list"); numbers.push(4); //UI not updating, but worked fine in Vue2 </script>
I know I could call app.dataArray.push
instead, or call $forceUpdate
etc., but is there a way to force Vue to simply watch the existing array?
I guess the broader question is: How to bind Vue3 to arbitrary pure JS objects? The object may be too complex to override, or it may come from an external API that I have no control over. This is simple in Vue2 or Angular (two-way binding to any normal object, whether it's part of an instance/component or not)
PS This looks like a huge breaking change in Vue3, but it's not mentioned anywhere.
renew:
Based on @Dimava's answer, it looks like the least painful way to fix the above code is:
var numbers = [1,2,3]; //this is my external array numbers = Vue.shallowReactive(numbers); //convert to a reactive proxy
P粉5384621872024-01-17 12:07:48
You need to make your arrayReactive
1
import { reactive, ref } from 'vue' const numbers = [1,2,3]; const reactiveNumbers = reactive(numbers) reactiveNumbers.push(4) // or, if you will need to reassign the whole array const numbersRef = ref(numbers) numbersRef.value.push(4) numbersRef.value = [3, 2, 1] // or, in the old style, if you are old const data = reactive({ numbers: [1, 2, 3] }) data.numbers.push(4) data.numbers = [3, 2, 1]
1 (or ShallowReactive
if it contains a lot of large objects that should not be responsive for performance reasons)