Динамически данные не обновляются при изменении входного значения v-модели в Vuejs

Я создаю погодное приложение с помощью этого Weather API. Я пытаюсь добавить значение поля <input>, которое при изменении названия города обновляет прогноз других значений.

Я создал поле <input>, которое обновляет значение города, и оно должно соответствующим образом обновлять прогноз погоды. Я знаю, что v-model работает, но это не меняет результатов. Только когда я жестко запрограммировал другой город в Vue-instance, данные обновляют изменения.

<template>
  <div class="home">
    <h1>{{ msg }}</h1>
    <p>A weather app built Vuejs & Open Weather App. Made by Manuel Abascal</p>
    <input type="text" v-model.lazy="currentWeather.name">
    <div class="forecast">
     <div v-if="this.currentWeather">
      <!-- Forecast stat values -->
      <h2>Right now:</h2>
      <div><strong>City:</strong> {{ currentCity }}</div>
      <div><strong>Longitude: </strong> {{ currentWeather.coord.lon }}</div>
      <div><strong>Latitude: </strong> {{ currentWeather.coord.lat }}</div>
      <div><strong>Weather condition </strong> {{ currentWeather.weather[0].description }}</div>
      <div><strong>Temperature Mid: </strong> {{  currentWeather.main.temp }} Farenheit</div>
      <div><strong>Temperature Max: </strong> {{  currentWeather.main.temp_max}} Farenheit</div>
      <div><strong>Temperature Min: </strong> {{  currentWeather.main.temp_min}} Farenheit</div>
      <div><strong>Humidity: </strong> {{  currentWeather.main.humidity }}%</div>
      <div><strong>Wind: </strong> {{  currentWeather.wind.speed }} mph</div>
     </div>
    </div>
  </div>
</template>

<script>
// import Axios
import axios from "axios"

export default {
  name: "Home",
  props: {
    msg: String,
  },
  data(){
    return {
      // current weather
      currentWeather: null,
      // current city
      currentCity: 'Montreal',
      // current country
      currentCountry: 'ca',
      unit: 'imperial'
    }
    this.$set(this.currentCity);
  },
  mounted(){
    // Make axios request to open weather api
    axios.get('https://api.openweathermap.org/data/2.5/weather?q='+this.currentCity+','+this.currentCountry+'&appid=fe435501a7f0d2f2172ccf5f139248f7&units='+this.unit+'')
    .then((response) => {
        // takes response object & stores it in currentWeather
        this.currentWeather = response.data

    })
    .catch(function (error) {
        // handle error
        console.log(error);
    })
  }
};
</script>

<style scoped lang="scss">

</style>

Я пытаюсь переехать в такие города, как Монреаль, Торонто, Оттава, Альберта и т. Д., Это меняет прогноз соответственно.


person Manuel Abascal    schedule 11.06.2019    source источник


Ответы (3)


У вас нет обработчика событий для currentCity изменений. Таким образом, ваш код будет работать при начальной загрузке (т.е. на mounted), и изменения в currentCity не повлияют на данные о погоде.

Вам нужно добавить @change во входные данные и получать новые данные API каждый раз, когда они меняются.

ниже пример кода

new Vue({
  el: '#app',
  data() {
    return {
      // current weather
      currentWeather: null,
      // current city
      currentCity: 'Montreal',
      // current country
      currentCountry: 'ca',
      unit: 'imperial'
    }
    this.$set(this.currentCity);
  },
  methods: {
    getWeather() {
      // Make axios request to open weather api
      fetch('https://api.openweathermap.org/data/2.5/weather?q=' + this.currentCity + ',' + this.currentCountry + '&appid=fe435501a7f0d2f2172ccf5f139248f7&units=' + this.unit + '')
        .then(res => res.json()).then(data => {
          // takes response object & stores it in currentWeather
          this.currentWeather = data;

        })
        .catch(function(error) {
          // handle error
          console.log(error);
        })
    }
  },
  mounted() {
    this.getWeather();
  }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.min.js"></script>
<div id="app">
  <div class="home">
    <p>A weather app built Vuejs & Open Weather App. Made by Manuel Abascal</p>
    Search: <input type="text" v-model.lazy="currentCity" @change="getWeather">
    <div class="forecast" v-if="currentWeather && currentWeather.cod == 200">
      <!-- Forecast stat values -->
      <h2>Right now:</h2>
      <div><strong>City:</strong> {{ currentWeather.name }}</div>
      <div><strong>Longitude: </strong> {{ currentWeather.coord.lon }}</div>
      <div><strong>Latitude: </strong> {{ currentWeather.coord.lat }}</div>
      <div><strong>Weather condition </strong> {{ currentWeather.weather[0].description }}</div>
      <div><strong>Temperature Mid: </strong> {{ currentWeather.main.temp }} Farenheit</div>
      <div><strong>Temperature Max: </strong> {{ currentWeather.main.temp_max}} Farenheit</div>
      <div><strong>Temperature Min: </strong> {{ currentWeather.main.temp_min}} Farenheit</div>
      <div><strong>Humidity: </strong> {{ currentWeather.main.humidity }}%</div>
      <div><strong>Wind: </strong> {{ currentWeather.wind.speed }} mph</div>
    </div>
    <div v-else>
      "{{ currentCity }}" is not found
    </div>
  </div>
</div>

person Ja9ad335h    schedule 11.06.2019

Есть две основные проблемы, которые мешают вашему коду работать так, как вы ожидаете.

v-модель

v-model во входных данных должно быть значением данных currentCity вместо значения currentWeather.name в ответе API.

Таким образом, когда ввод изменяется, currentCity будет обновлен, и вы сможете отреагировать на его изменение и запросить новые данные.

запрос данных

Выполнение запроса погоды в ловушке mounted позволяет получить данные только один раз, поскольку эта ловушка больше не выполняется в течение жизни компонента, изменение города ничего не даст.

решение

Я бы изменил v-model на currentCity и добавил наблюдателя на currentCity, чтобы при изменении он запускал вызов функции, которая получает информацию о погоде, а также, делая этот наблюдатель незамедлительно, гарантирует, что он будет работать и при монтировании компонентов.

У меня есть jsfiddle здесь с обновленным кодом.

person Leite    schedule 11.06.2019

У вас есть две проблемы:

Сначала ввод привязан к currentWeather.name вместо currentCity.

Во-вторых, у вас есть запрос axios в смонтированном жизненном цикле. Даже если модель currentCity изменится, вы не определяете, что произойдет, когда она изменится. Вам нужно добавить вызов api при изменении currentCity.

  1. Измените модель входа на currentCity <input type="text" v-model="currentCity">

  2. Переместите запрос axios в собственный метод

    getWeather() {
        const url = 'https://api.openweathermap.org/data/2.5/weather?q=' + this.currentCity + ',' + this.currentCountry + '&appid=fe435501a7f0d2f2172ccf5f139248f7&units=' + this.unit + '';
        axios.get(url)
            .then((response) => {
                this.currentWeather = response.data;
            })
            .catch(function(error) {
                console.log(error);
            })
    }
    
  3. Привяжите изменение ввода к методу getWeather

Вы можете добавить событие getWeather к методу ввода input currentCity.

<input type="text" v-model="currentCity" @input="getWeather">

или добавить наблюдателя для текущей погоды

watch: {
    currentCity: function(newCity, oldCity) {
        this.getWeather();
    }
}

бонус

каждый раз, когда вы записываете или стираете букву ввода, метод срабатывает. Добавьте дебаунс или тайм-аут, и он сработает через миллисекунды.

// import Axios
import axios from "axios"

export default {
    name: "Home",
    props: {
        msg: String,
    },
    data() {
        return {
            currentWeather: null,
            currentCity: 'Montreal',
            currentCountry: 'ca',
            unit: 'imperial'
        };
    },
    watch: {
        currentCity: function(newCity, oldCity) {
            this.debounceGetWeather();
        },
    },
    mounted() {
        this.getWeather();
    },
    methods: {
        debounceGetWeather() {
            setTimeout(() => {
                this.getWeather();
            }, 300);
        },
        getWeather() {
            axios.get('https://api.openweathermap.org/data/2.5/weather?q=' + this.currentCity + ',' + this.currentCountry + '&appid=fe435501a7f0d2f2172ccf5f139248f7&units=' + this.unit + '')
                .then((response) => {
                    this.currentWeather = response.data '
                })
                .catch(function(error) {
                    console.log(error);
                })
        },
    },
};
person larizzatg    schedule 11.06.2019