VueJS обновляет localStorage в Axios Response - PullRequest
2 голосов
/ 03 октября 2019

Краткий обзор
По сути, я создаю простой виджет погоды, в который вы вводите название города, и он запускает запрос API и получает объект погоды для этого города.

Триггеры для запроса формы / API: debounce, когда кто-то прекращает печатать, и onsubmit, когда кто-то нажимает клавишу ввода внутри ввода.

Проблема
Когда кто-то ищет город, у меня есть функция watch, которая устанавливает значение localStorage city равным тому, что пользователь ввел на лету.

Проблема в том, что еслигорода, который они искали, не существует, тогда он все равно будет сохранен в локальном хранилище, и при перезагрузке страницы он убивает виджет, потому что запрос API не может получить информацию об этом городе.

I 'мы пытались применить значение локального хранилища, если статус ответа 200 из запроса, но наблюдатель просто перезаписывает его.

Так что в основном мне нужно установить значение localStorage, когда ответ равен 200, и удалить его, если это не так.

Я пытался сделать оператор if, когда ответ200 и когда это не так, но значение в Local Storage не изменяется.

Логически я не думаю, что наблюдатель нужен, и значение city не должно обновляться, пока ответ на запрос не станет 200.

Пожалуйста, посмотрите на мой пример здесь: https://jsfiddle.net/mattclarke/mjswgb63/

Действия по копированию моей проблемы

  1. Замените London на Liverpool, чтобы увидеть обновление ключа в Application -> LocalStorage.
  2. Измените Liverpool на несуществующий город, например Londonpool.
  3. Обновите страницу, и вы увидите, что виджет не отображается.
  4. Измените *Значение 1050 * в локальном хранилище возвращается к London или любому другому названию города.
  5. Обновите страницу, и она должна снова работать.

Код

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>&#176;c</div>
                    <div><span class="text-blue-400 text-xs">Max: </span><span class="text-white" data-temp-max>{{ weather.main.temp_max }}</span>&#176;c</div>
                    <div><span class="text-blue-400 text-xs">Min: </span><span class="text-white" data-temp-min>{{ weather.main.temp_min }}</span>&#176;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>&#176;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>

Буду признателен за любую помощь!

1 Ответ

1 голос
/ 03 октября 2019

Мне удалось заставить это работать так, как должно. Я просто должен был удалить ключ localStorage, если ответ не был успешным.

Правильный код для метода weatherRequest ниже:

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) {
            localStorage.city = cityName;
        }
        Toast.fire({
            type: 'success',
            title: cityName + ' was loaded successfully.'
        });
    }, () => {
        this.loading = false;
        window.localStorage.removeItem('city');
        Toast.fire({
            type: 'error',
            title: 'Couldn\'t find the city: ' + cityName,
        })
    })
},
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...