Issue
I successfully get data from an external js file (long Json process, exports promise function), but the data it's not been added to the component on the first try. I have to enter in a different component and then when returning the data is shown.
I have tried using the beforeCreate() method, but it hasn't help, the condole.log(data) shows the information, but the component is not.
<template>
<div class="roomsBar">
<div class="roomsArea">
<li v-for="building in allBuildings" :key="building">
<a v-on:click="clicked(building)">{{building}}</a>
</li>
</div>
</div>
</template>
<script>
import {menuData as menuData} from '../controllers/navigation.js';
export default {
name: 'Buildings',
data() {
return {
allBuildings: window.menu
}
},
methods: {
clicked: function(item){
this.$router.push({ path: '/navigation/'+item })
}
},
beforeCreate() {
window.menu = [];
menuData().then((data) => { // Recover the data from 'Navigation.js'
console.log(data);
for (const element of data) { // Filter data and only add building to the menu
window.menu.push(element.building);
}
console.log(window.menu);
});
}
}
</script>
<style scoped>
.roomsBar {
width: 100%;
height: 100%;
background-color: #fff;
}
li {
list-style-type: none;
}
a {
cursor: pointer;
color: #42b983;
}
</style>
I need that the data to be showed on the first try.
I'm actually new in vue by the way.
Solution
The reason this isn't working is because Vue cannot track when window.menu
changed, and is therefore unable to re-render as such.
Your entire use of window
for this is dubious at best. Consider the following:
let menuData = function() {
return new Promise(function(resolve, reject) {
setTimeout(function() {
return resolve([{
name: 'test'
},
{
name: 'test 2'
}
]);
}, 100);
});
}
let component = Vue.component('test', {
name: 'Buildings',
template: '<ul><li v-for="item in allBuildings">{{item.name}}</li></ul>',
data: () => ({
allBuildings: []
}),
beforeCreate() {
menuData().then((data) => {
this.$set(this.$data, 'allBuildings', data);
});
}
});
let app = new Vue({
el: "#app"
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<test></test>
</div>
With this small rewrite, we achieved multiple things:
- you no longer depend on an array stored outside of this item (I.e.
window
), preferring to leverage a property of your object itself - Vue now clearly knows when the array changes, as we are calling
$set
- the link between the two is now explicit
More information about $set
/Vue.set
is available on the Vue documentation and is the main way to store and update reactive data.
Regarding the for
loop and filtering, if you are never going to refresh this component's data, it is perfectly fine to keep push
ing to the array, like so:
menuData().then((data) => {
for (const element of data) {
this.$data.allBuildings.push(element);
}
});
Vue.js directly supports most array mutation methods straight on the data object itself; if you find yourself in the case where you need to filter an array, making use of those or building the array separately then $set
ting it would also work.
Answered By - Sébastien Renauld Answer Checked By - Cary Denson (PHPFixing Admin)
0 Comments:
Post a Comment
Note: Only a member of this blog may post a comment.