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

Я создаю приложение погоды с этим 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>

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

Ответы [ 3 ]

1 голос
/ 11 июня 2019

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

v-модель

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

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

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

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

решение

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

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

1 голос
/ 11 июня 2019

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

Сначала вход связывается с currentWeather.name вместо currentCity

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

  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 к методу ввода для ввода 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);
                })
        },
    },
};
1 голос
/ 11 июня 2019

У вас нет обработчика событий для 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>
...