我想了解 vue.js组件和与用户交互的数据绑定,任何人都可以纠正我的代码并向我解释一下



我是一个初学者开发人员,目前我正在使用 vue 进行天气应用程序项目.js .我在使用 vue 的组件和数据绑定方面遇到了一些问题。谁能用一些代码示例向我解释一下?!

我读过一些论坛,看了一些关于自定义组件的教程视频,也试过了,但我想我犯了一些错误。具体来说,我想知道,如何将我的 API url 数据绑定到下拉框,位置会随着每次选择而变化。

注意:使用的 API 是基于纬度和经度位置的开放天气 API。

var myDropdown = Vue.component('my-dropdown', {
  template: '#dropdown',
data: function() {
  return {
    isOpen: false,
    selected: null,
    options: [
      'Heidenheim an der Brenz',
      'Giengen',
      'Ulm',
    ]
  }
},
  methods: {
    toggle: function() {
      this.isOpen = !this.isOpen;
    },
    show: function() {
      this.isOpen = true;
    },
    hide: function() {
      this.isOpen = false;
    },
  set: function(option) {
    this.selected = option;
    this.hide();
  }
  },
  mounted: function() {
    console.log('My dropdown component is mounted!')
  }
});
let weatherApp = new Vue({
  el: '#app',
  data: {
  	town: '',
    Temp: '',
    minTemp: '',
    maxTemp:'',
    wind: '',
    description: '', 
    icon: '',
    hdh: 'https://fcc-weather-api.glitch.me/api/current?lat=48.6833&lon=10.15',
    ulm: 'https://fcc-weather-api.glitch.me/api/current?lat=48.39841&lon=9.99155',
    giengen: 'https://fcc-weather-api.glitch.me/api/current?lat=48.39841&lon=9.99155'
  },
  methods: {
    getWeather() {
 			var url = '';
      axios
        .get(url)
        .then(response => {
       		this.town = response.data.name
          this.Temp = response.data.main.temp;
          this.minTemp = response.data.main.temp_min;
          this.maxTemp = response.data.main.temp_max;
          this.wind = response.data.wind.speed;
          this.description = response.data.weather[0].description;
          this.icon = response.data.weather[0].icon;
      })
      .catch(error => {
        console.log(error);
      });
    },
  },
  beforeMount() {
    this.getWeather();
  },
});
body {
  background: url(https://shiftyjelly.files.wordpress.com/2013/11/w.jpg?w=960&h=400);
  background-repeat: no-repeat;
  font-family: 'Montserrat', sans-serif;
  font-weight: 100;
  text-shadow: 0px 0px 2px #000000;
  color: #ffffff;
  width: 960px;
  height: 400px;
}
#weather {
  padding: 15px;
}
#temperature {
  position: absolute;
  font-size: 40px;
  top: 240px;
  left: 420px;
  color: black;
}
#temp-values {
  text-align: right;
  position: relative;
  text-justify: distribute;
  display: block;
  top: 60px;
  left: -200px;
  color: black;
}
#info {
  padding: 15px;
}
#name {
  top: 10px;
  left: 300px;
  font-size: 40px;
  color: black;
  position: relative;
}
.wind {
  top: 180px;
  left: 380px;
  color: black;
  position: relative;
}
#icon {
  color: black;
  font-size: 20px;
  left: -180px;
  top: 120px;
  position: relative;
}
#my-dropdown {
  cursor: pointer;
  position: absolute;
  left: 0%;
  top: 0%;
  min-width: 250px;
  height: 40px;
}
#selected {
  position: relative;
  z-index: 2;
  display: block;
  width: 100%;
  height: 40px;
  padding: 0 20px;
  background: rgba(05, 46, 41, 0.1);
  border-radius: 10px;
  font: 1.25rem/40px 'Ubuntu', Helvetica, Arial, sans-serif;
  text-shadow: 2px 2px 0px #000;
  color: rgb(0, 237, 255);
}
#selected: after {
  opacity: 0.5;
  display: inline-block;
  margin-left: 10px;
  content: '▼';
  color: black;
}
#selected:hover: after {
  opacity: 1;
}
#options {
  position: absolute;
  left: 0;
  top: 100%;
  z-index: 1;
  width: 100%;
  margin-top: 3px;
  background: rgba(05, 46, 41, 0.1);
  border-radius: 10px;
}
#option {
  padding: 5px 20px;
  border-bottom: 1px solid rgba(0, 0, 0, 0.25);
  font: 1.2rem 'Vollkorn', Georgia, Times, serif;
  color: rgb(0, 237, 255);
  text-shadow: 2px 2px 0px #000;
}
#option:hover {
  background-color: rgba(0, 0, 0, 0.05);
}
#option:last-child {
  border-bottom: none;
}
#fade-enter-active, .fade-leave-active {
  transition: all 0.25s ease-out;
}
#fade-enter, .fade-leave-active {
  opacity: 0.5;
	transform: translateY(-30px);
}
* { box-sizing: border-box; }
<html>
  <head>
    <meta charset="utf-8">
    <meta http-equiv="x-ua-compatible" content="ie=edge">
    <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.2.1/vue.js"></script>
    <title>Weather App</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
  </head>
<template id="dropdown">
  <div id="my-dropdown">
  <div id="selected" @click="toggle">Select Your Town Here</div>
    <div id="options" v-show="isOpen">
    <div id="option" v-for="option in options" @click="set(option)">
      {{ option }}
    </div>
    </div>
  </div>
</template>
  <body>
   <div id="app">
   <my-dropdown></my-dropdown>
  <div id="weather">
    <span id="name">{{town}}</span>
    <span id="icon">{{description}}</span>
    <span id="temperature">{{Temp}}°</span><br>
    <span id="temp-values">Min: {{minTemp}}° <br> Max: {{maxTemp}}°</span>
  </div>
  <div id="info">
    <img class="wind" height="40px" width="40px" src="https://www.svgrepo.com/show/71601/wind.svg"> 
    <span class="wind">{{wind}} m/s</span>
  </div>
  </div>
    <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
  </body>
</html>

这是一个小提琴

首先,最好将所有数据保存在一个位置,而不是在下拉组件中对城镇名称进行硬编码。 您也不需要每次都存储整个 URL。 因此,请从下拉列表中删除options。您将通过道具将城镇数据传递给它。

1( 将应用的城镇数据重组为对象数组,如下所示:

data: {
  ...
  towns: [
    {abbr: 'hdh', name: 'Heidenheim an der Brenz', lat: '48.6833', lon: '10.15'},
    {abbr: 'ulm', name: 'Ulm', lat: '48.39841', lon: '9.99155'},
    {abbr: 'giengen', name: 'Giengen', lat: '48.39841', lon: '9.99155'}
  ]
}

2( 通过名为"选项"的道具将城镇数据传递给下拉组件:

<my-dropdown :options="towns"></my-dropdown>

3( 将下拉标签更改为{{ option.name }}

4(将道具添加到组件中:

props: ['options']

5( 当城镇发生变化时发出自定义事件:

set: function(option) {
  this.$emit('change-town', option);
  ...
}

6( 在父模板的getWeather中处理该事件:

<my-dropdown :options="towns" @change-town="getWeather"></my-dropdown>

7( 生成 URL 并发送请求:

getWeather(option) {
  const urlpath = 'https://fcc-weather-api.glitch.me/api/current?'
  const qs = `lat=${option.lat}&lon=${option.lon}`;
  const url = path + qs;
  axios.get(url)...
  ...
}

最新更新