Краткий обзор
По сути, я создаю простой виджет погоды, в который вы вводите название города, и он запускает запрос API и получает объект погоды для этого города.
Триггеры для запроса формы / API: debounce
, когда кто-то прекращает печатать, и onsubmit
, когда кто-то нажимает клавишу ввода внутри ввода.
Проблема
Когда кто-то ищет город, у меня есть функция watch
, которая устанавливает значение localStorage city
равным тому, что пользователь ввел на лету.
Проблема в том, что еслигорода, который они искали, не существует, тогда он все равно будет сохранен в локальном хранилище, и при перезагрузке страницы он убивает виджет, потому что запрос API не может получить информацию об этом городе.
I 'мы пытались применить значение локального хранилища, если статус ответа 200 из запроса, но наблюдатель просто перезаписывает его.
Так что в основном мне нужно установить значение localStorage
, когда ответ равен 200, и удалить его, если это не так.
Я пытался сделать оператор if
, когда ответ200
и когда это не так, но значение в Local Storage не изменяется.
Логически я не думаю, что наблюдатель нужен, и значение city
не должно обновляться, пока ответ на запрос не станет 200.
Пожалуйста, посмотрите на мой пример здесь: https://jsfiddle.net/mattclarke/mjswgb63/
Действия по копированию моей проблемы
- Замените
London
на Liverpool
, чтобы увидеть обновление ключа в Application -> LocalStorage
. - Измените
Liverpool
на несуществующий город, например Londonpool
. - Обновите страницу, и вы увидите, что виджет не отображается.
- Измените *Значение 1050 * в локальном хранилище возвращается к
London
или любому другому названию города. - Обновите страницу, и она должна снова работать.
Код
import axios from 'axios'
import Swal from 'sweetalert2'
import _ from 'lodash'
const Toast = Swal.mixin({
toast: true,
position: 'top-end',
showConfirmButton: false,
timer: 3000
})
export default {
name: 'app',
data() {
return {
weather: [],
city: 'London',
loading: false,
}
},
mounted() {
this.weatherRequest();
},
watch: {
city(city) {
localStorage.city = city;
}
},
methods: {
weatherRequest: function() {
this.loading = true;
if(localStorage.city) {
this.city = localStorage.city;
}
let cityName = this.city;
if(cityName == "") {
this.loading = false;
return;
}
axios
.get('http://api.openweathermap.org/data/2.5/weather?q=' + cityName + '&APPID=757cfb0ae831a41efa790e4fd9b008e8&units=metric')
.then(response => {
this.loading = false;
this.weather = response.data;
if(response.status == 200) {
}
Toast.fire({
type: 'success',
title: cityName + ' was loaded successfully.'
});
}, () => {
this.loading = false;
Toast.fire({
type: 'error',
title: 'Couldn\'t find the city: ' + cityName,
})
})
},
getWeather: function() {
this.weatherRequest()
},
debounceWeather: _.debounce(function() {
this.weatherRequest()
}, 700),
}
}
<template>
<div id="app">
<form v-on:submit.prevent="weatherRequest" class="mb-2 max-w-2xl mx-auto flex">
<input type="text" v-model="city" class="border-2 p-2 w-full" @input="debounceWeather" placeholder="Please specify a city name" data-city-name>
</form>
<div class="max-w-2xl mx-auto">
<div class="flex w-full rounded-lg" style="background: url('http://placeimg.com/640/480/nature');">
<div class="text-white p-6 rounded-lg shadow-lg text-sm w-full relative" style="background-color: rgba(42, 67, 101, 0.75); backdrop-filter: blur(5px);" data-weather-box>
<div v-if="loading" class="absolute bg-blue-900 flex h-full items-center justify-center left-0 opacity-75 rounded-lg top-0 w-full"><img src="./assets/loading.svg" /></div>
<div class="border-b-2 border-blue-800 mb-4 pb-4 flex justify-between">
<div class="text-left">
<div class="block text-lg">
<span data-city-result>{{ weather.name }}</span> (<span data-country>{{ weather.sys.country }}</span>)
</div>
<span class="text-blue-300" data-weather>{{ weather.weather[0].main }} - {{ weather.weather[0].description }}</span>
</div>
<div class="absolute p-3 pr-5 right-0 text-5xl top-0 weather">
<i v-if="weather.weather[0].main == 'Clouds'" class="fas fa-cloud"></i>
<i v-if="weather.weather[0].main == 'Clear'" class="fas fa-sun text-yellow-400"></i>
<i v-if="weather.weather[0].main == 'Rain'" class="fas fa-cloud-rain"></i>
<i v-if="weather.weather[0].main == 'Snow'" class="far fa-snowflake"></i>
<i v-if="weather.weather[0].main == 'Mist'" class="fas fa-smog"></i>
<i v-if="weather.weather[0].main == 'Smoke'" class="fas fa-smog"></i>
<i v-if="weather.weather[0].main == 'Haze'" class="fas fa-smog"></i>
<i v-if="weather.weather[0].main == 'Thunderstorm'" class="fas fa-bolt"></i>
</div>
</div>
<div class="flex justify-between">
<div><span class="text-blue-400 text-xs">Temp: </span><span class="text-white" data-temp>{{ weather.main.temp }}</span>°c</div>
<div><span class="text-blue-400 text-xs">Max: </span><span class="text-white" data-temp-max>{{ weather.main.temp_max }}</span>°c</div>
<div><span class="text-blue-400 text-xs">Min: </span><span class="text-white" data-temp-min>{{ weather.main.temp_min }}</span>°c</div>
</div>
<div class="flex justify-between">
<div><span class="text-blue-400 text-xs">Pressure: </span><span data-pressure>{{ weather.main.pressure }}</span></div>
<div><span class="text-blue-400 text-xs">Humidity: </span><span data-humidity>{{ weather.main.humidity }}</span></div>
<div><span class="text-blue-400 text-xs">Visibility: </span><span data-visibility>{{ weather.visibility }}</span></div>
</div>
<div class="flex justify-between">
<div><span class="text-blue-400 text-xs">Wind Speed: </span><span data-wind-speed>{{ weather.wind.speed }}</span>mph</div>
<div><span class="text-blue-400 text-xs">Wind Direction: </span><span data-wind-direction>{{ weather.wind.deg }}</span>°deg</div>
</div>
<div class="flex justify-between">
<div><span class="text-blue-400 text-xs">Sunrise: </span><span data-sunrise>{{ new Date(weather.sys.sunrise * 1000).toLocaleString() }}</span></div>
<div><span class="text-blue-400 text-xs">Sunset: </span><span data-sunset>{{ new Date(weather.sys.sunset * 1000).toLocaleString() }}</span></div>
</div>
</div>
</div>
</div>
</div>
</template>
Буду признателен за любую помощь!