Vue.js v-for list not updating
I have this list:
<ul id="tab"> <li v-for="list in names"> {{ list.personName }} </li> </ul> And then I have this vue object:
var vm = new Vue ({ el: '#tab', data: { names: //an object array coming from the server } }); So, these 'names' are updated and receive information from the server. However, when the names are updated / changed, they are not reflected in the list of client parties. The items displayed in the list reflect only those items that were there when the page was originally loaded.
In the vue.js developer tools in Google Chrome, I can always see the updated data "names", but it just does not reflect the DOM itself.
EDIT1 : What's in 'name's:
names: Array[2] 0: Object _id: "580aeafd017fbfb81a3a794d" personName: "hi" 1: Object _id: "580c4455ccc9e39c21f02434" personName: "test" EDIT2
So, I am using node.js and transmitting real-time data from node to the client through socket.io as follows:
socket.on('userDocument', function(userDocument) { var vm= new Vue ({ el: '#tab', data: { names: //an object array coming from the server } }); }); Detecting array changes is a bit more complicated in Vue. Most in-place array methods work as expected (ie, performing a splice in your $ data.names array will work), but using values ββdirectly (for example, $ data.names [0] = 'Joe') will not update reactively displayed components. Depending on how you process the results on the server side, you may need to think about these options described in the vue documentation: Detecting array changes .
Some ideas to learn:
- using v-bind: key = "some_id" to better
- by clicking to add new items
- using Vue.set (example1.items, indexOfItem, newValue) (also mentioned Artokun)
I am not an expert on sockets, but this is not the recommended way to access a socket connection.
The socket establishes a permanent connection with the server, and you can receive data at any time from the server. Your socket.on("message", function(data) {...}) is the processor of this asynchronous data from the server.
In your code example, your message handler creates a new instance of Vue() every time the server sends some data. You will quickly get multiple versions of Vue() instances, which will potentially lead to a crash of the user browser tab using hogging memory.
I do not use socket.io , but based on my understanding of web applications in general, here is how I would like to do this:
// Initialize your Vue app first: new Vue ({ el: '#tab', template: ` <ul id="tab"> <li v-for="list in names"> {{ list.personName }} </li> </ul> ` data: { names: [] // start with blank, and modify later }, created: function() { // This 'created' hook is called when your Vue instance is setup // TODO: Initialize your socket connection here. // ... // Setup your socket listener mySocketInstance.on("message", response_data => { // Assuming your response_data contains 'user_names' array this.names = response_data.user_names; // Note: 'this' in the above line points to outer scope, that is why we need arrow functions }) } }); This code may work for you. You still have to test and debug a lot. But so I expected that everything will work.
Note:
The sample code creates only one instance of
Vue()and initializes the socket listener in hookcreated. So there is only one listener / handler for your socket messages.The socket message handler uses the javascript arrow function, which ensures that your outer region
thismatches the inner regionthis. This way you can correctly updatenames.