VueJS在Axios响应上更新localStorage

时间:2019-10-03 10:02:04

标签: javascript vue.js vuejs2 axios

简要概述
我基本上是在构建一个简单的天气小部件,在其中输入城市名称,它将从API请求中触发并获取该城市的天气对象。

表单/ API请求的触发器是当某人停止键入时通过debounce和当某人在输入中按下回车键时通过onsubmit

问题
当有人搜索城市时,我有一个watch函数,该函数将localStorage键city设置为等于用户即时输入的任何内容。

问题是,如果不存在他们搜索的城市,则该城市仍将保存在本地存储中,并且当页面重新加载时,它会杀死小部件,因为API请求无法获取该城市的详细信息

如果请求的响应状态为200,我已经尝试应用本地存储值,但是观察者只是将其覆盖。

因此,基本上,我需要在响应为200时设置localStorage值,如果不是,则将其删除。

我尝试过执行if语句来确定何时响应为200,何时不响应,但是Local Storage中的值不变。

从逻辑上讲,我认为不需要观察者,并且在请求的响应为200之前,不应更新city值。

请在此处查看我的示例:https://jsfiddle.net/mattclarke/mjswgb63/

复制我的问题的步骤

  1. London替换为Liverpool,以查看Application -> LocalStorage中的密钥更新。
  2. Liverpool更改为不存在的城市,例如Londonpool
  3. 刷新页面,您将看到小部件无法显示。
  4. 将“本地存储”中的city值改回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 个答案:

答案 0 :(得分:1)

我设法使它按应有的方式工作。如果响应不成功,我只需要删除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,
        })
    })
},