Every time I add an element it automatically replaces all the others but this happens to me only if I insert the whole object if I insert a classic element an integer a string works without problems.
<body>
<div id="app">
<button @click="post()">POST</button>
<h1>{{ar.name}} {{ar.surname}} {{ar.gender}}</h1>
<br />
<hr />
<div v-for="(value, index) in array">
<text>{{index}} {{value}} </text>
</div>
</div>
<script src="https://unpkg.com/vue@3"></script>
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<script>
let app = Vue.createApp({
data: function () {
return {
ar: {
name: "",
surname: "",
gender: "",
},
array: [],
};
},
methods: {
async post() {
await axios
.get("https://randomuser.me/api/")
.then((r) => {
arr = r.data.results;
arr.forEach((element) => {
this.ar.name = element.name.first;
this.ar.surname = element.name.last;
this.ar.gender = element.gender;
this.array.push(this.ar);
});
})
.catch((err) => {
console.log("Error " err);
});
},
},
});
app.mount("#app");
</script>
</body>
</html>
CodePudding user response:
You have a pointer reference issue. You actually add the same object pointer several times to the array, i.e. the same object reference:
Explaination of the problem
const obj = { name: 'ref1' };
const array = [];
array.push(obj);
array.push(obj);
array.push(obj);
// array === [{ name: 'ref1' }, { name: 'ref1' }, { name: 'ref1' }]
// which is actually [$objRef1, $objRef1, $objRef1] where $objRef1 is a pointer to the object address.
// when you updates the object,
obj.name = 'Hello'
// you still have array = [$objRef1, $objRef1, $objRef1] where $objRef1 all referes to this object: { name: 'Hello' }
// array === [{ name: 'Hello' }, { name: 'Hello' }, { name: 'Hello' }]
Solution:
You have to create a new object on every iteration, so they all are distinct object which a distinct address (pointer).
await axios
.get("https://randomuser.me/api/")
.then((r) => {
const arr = r.data.results;
arr.forEach((element) => {
const item = {
name: element.name.first,
surname: element.name.last,
gender: element.gender,
};
this.ar = item // refers to the new created item
this.array.push(item);
});
}).catch((err) => {
console.log("Error " err);
});
CodePudding user response:
You can assign the response in an object inside the iteration and pass that in the this.ar
. Try this way :
const URL = "https://randomuser.me/api/";
new Vue({
el: '#app',
data() {
return {
ar: {
name: "",
surname: "",
gender: "",
},
userArray: [],
}
},
methods: {
post() {
axios.get(URL).then((r) => {
arr = r.data.results;
arr.forEach((element) => {
let obj = {};
obj.name = element.name.first;
obj.surname = element.name.last;
obj.gender = element.gender;
this.ar = obj;
this.userArray.push(obj);
});
})
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.17.1/axios.js"></script>
<div id="app">
<button @click="post()">POST</button>
<h1>{{ar.name}} {{ar.surname}} {{ar.gender}}</h1>
<br />
<hr />
<div v-for="(value, index) in userArray" :key="index">
<span> {{index}} {{value}} </span>
</div>
</div>