programing

Vuejs에서 v-model 입력 값을 변경할 때 데이터가 동적으로 업데이트되지 않음

shortcode 2022. 7. 16. 14:09
반응형

Vuejs에서 v-model 입력 값을 변경할 때 데이터가 동적으로 업데이트되지 않음

는 이 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>

몬트리올, 토론토, 오타와, 앨버타 등의 도시로 바꾸려고 합니다.그에 따라 예보가 변경됩니다.

이벤트 핸들러가 없습니다.currentCity변화들.따라서 코드는 초기 로드 시(즉,mounted및 변경 사항currentCity날씨 데이터는 변경되지 않습니다.

를 추가해야 합니다.@changeapi 데이터가 변경될 때마다 새로운 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>

코드가 예상대로 작동하지 않는 주요 문제는 두 가지입니다.

v-model

v-model입력에 필요한 것은currentCityAPI로부터의 응답 값 대신 데이터 값currentWeather.name.

이 방법으로 입력이 변경되면currentCity갱신됩니다.변경에 대응하여 새로운 데이터를 요구할 수 있습니다.

요청 데이터

날씨에 대한 요청을 받은 경우mounted훅은 컴포넌트 수명 동안 다시 실행되지 않기 때문에 한 번만 데이터를 얻어도 괜찮습니다.

해결 방법

제가 바꿀게요.v-model되려고currentCity와 워처를 추가합니다.currentCity따라서 변경되면 날씨를 얻는 함수에 대한 호출이 트리거되며, 또한 이 워처가 즉시 컴포넌트 마운트에서도 실행되도록 합니다.

업데이트된 코드로 jsfiddle을 준비했습니다.

다음 두 가지 문제가 있습니다.

첫 번째 입력은 currentCity가 아닌 currentWeather.name으로 바인드됩니다.

둘째, 마운트된 라이프 사이클에 Axios 요청이 있습니다.currentCity 모델이 변경되더라도 변경 시 발생하는 작업을 정의하지 않습니다.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">

또는 currentWeather에 워처를 추가합니다.

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);
                })
        },
    },
};

언급URL : https://stackoverflow.com/questions/56546715/dynamically-data-doesnt-update-when-changing-v-model-input-value-in-vuejs

반응형