Laravel Vue js. Почему не обновляется значение в data?
Делаю запрос к api, получаю данные, но когда вывожу их в консоль, они оказываются пустыми, но при выводе в шаблон все нормально. Как мне сделать запрос и иметь уже готовые данные, чтобы работать с ними в при монтировании компонента?
<script>
import axios from 'axios'
export default{
data(){
return{
statusNew : '',
progress : 0,
order_id : '',
order : [],
segments : [],
}
},
methods:
{
getData()
{
axios.defaults.headers.common['Authorization'] = 'Bearer ' + localStorage.getItem('access_token')
axios.get("api/orders")
.then((response) =>{
this.segments = response.data.segments;
this.order = response.data.order;
this.order_id = response.data.order.id;
if(this.order.status=='awaiting'){
this.statusNew = 'Скоро начнет готовиться'
this.progress = 25
}
else if(this.order.status=='cooking'){
this.statusNew = 'Готовиться'
this.progress = 50
}
else if(this.order.status=='delivery'){
this.statusNew = 'Идет доставка'
this.progress = 75
}
else if(this.order.status=='completed'){
this.statusNew = 'Доставлен'
this.progress = 100
}
});
},
},
mounted()
{
this.getData();
console.log(this.order_id); // пустые
Echo.channel('orders-tracker.'+ this.order_id)
.listen('OrderStatusChanged', (order) => {
this.statusNew = order.status_name
this.progress = order.status_percent
});
}
}
</script>
Ответы (2 шт):
Вы когда выполняете getData, запускается асинхронный запрос к api. Следовательно когда пишите в консоль, ответ от сервера еще не получен. Гуглите подробнее принцип асинхронных запросов axios.
Вам нужно использовать await async в данном методе или задействовать переменную со статусом загрузки. Например создать loading со статусом false и когда присвоите все переменные из api, перевести ее в true и в шаблоне выводить данные только когда loading положительный.
Первый вариант:
Vue.component('my-component', {
data() {
return {
apiUrl: 'https://api.themoviedb.org/3/discover/movie?api_key=15d2ea6d0dc1d476efbca3eba2b9bbfb'
}
},
mounted() {
this.init();
},
methods: {
async getData() {
try {
const response = await axios.get(this.apiUrl);
if (response.status !== 200)
throw new Error('Bad status code');
return response.data.results;
} catch(error) {
console.log(error.message);
return;
}
},
async init() {
const movies = await this.getData();
console.log(movies);
}
},
template: `<span>My component</span>`
});
new Vue({ el: "#app" })
body {
background: #20262E;
padding: 20px;
font-family: Helvetica;
}
#app {
background: #fff;
border-radius: 4px;
padding: 20px;
transition: all 0.2s;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.19.2/axios.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<my-component />
</div>
Второй вариант:
Vue.component('my-component', {
data() {
return {
movies: [],
apiUrl: 'https://api.themoviedb.org/3/discover/movie?api_key=15d2ea6d0dc1d476efbca3eba2b9bbfb'
}
},
mounted() {
this.loadData();
},
methods: {
async loadData() {
try {
const response = await axios.get(this.apiUrl);
if (response.status !== 200)
throw new Error('Bad status code');
this.movies = response.data.results;
} catch(error) {
console.log(error.message);
return;
}
},
afterLoadDataHandle() {
console.log(this.movies);
}
},
watch: {
movies: function(value) {
if (value.length > 0)
this.afterLoadDataHandle();
}
},
template: `<span>test</span>`
});
new Vue({ el: "#app" })
body {
background: #20262E;
padding: 20px;
font-family: Helvetica;
}
#app {
background: #fff;
border-radius: 4px;
padding: 20px;
transition: all 0.2s;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.19.2/axios.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<my-component />
</div>