主要:1.了解如何兄弟通信 以及全局总线的使用一个触发事件传参数一个在 挂载后 里面接收兄弟传来的参数 然后调函数 传入参数 完成数据通信 动态绑定
组件的构建(app 父 search ,weather儿子 )
- 创建组件
- 注册组件
- 使用组件
父 APP
<template>
<div id="app" class="card">
<SearchBOX></SearchBOX>
<WeatherBODY></WeatherBODY>
</div>
</template>
<script>
import SearchBOX from './components/Search.vue'
import WeatherBODY from './components/Weather.vue'
export default {
name: 'App',
components: { SearchBOX, WeatherBODY },
}
</script>
<style lang="css">
* {
margin: 0;
padding: 0;
font-family: 'Poppins', sans-serif;
box-sizing: border-box;
}
body {
background: #222;
}
.card {
width: 70%;
max-width: 470px;
background: linear-gradient(135deg, #00feba, #5b548a);
color: #fff;
margin: 100px auto 0;
border-radius: 20px;
padding: 40px 35px;
text-align: center;
}
</style>
俩儿子
<template>
<div class="weather">
<!-- 提示信息:您输入的城市名不存在 -->
<div v-show="isNotFound">对不起,请检查您的城市名!</div>
<img :src="weather.imgPath" class="weather-icon">
<h1 class="temp">{{weather.temp}}°c</h1>
<h2 class="city">{{weather.city}}</h2>
<div class="details" >
<div class="col">
<img src="../assets/images/humidity.png" />
<div>
<p class="humidity">{{weather.humidity}}%</p>
<p>湿度</p>
</div>
</div>
<div class="col">
<img src="../assets/images/wind.png">
<div>
<p class="wind">{{weather.windSpeed}} 米/秒</p>
<p>风力</p>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'WeatherBODY',
data() {
return {
isNotFound: false,
weather: {}
}
},
methods:{
displayWeather(weather, isNotFound){
this.weather = weather
this.isNotFound = isNotFound
},
displayNotFound(isNotFound){
this.isNotFound = isNotFound
}
},
//接收来自兄弟组件传过来的数据 挂载后就接收
mounted() {
this.$bus.$on('displayWeather',this.displayWeather )
this.$bus.$on('displayNotFound', this.displayNotFound)
},
beforeDestroy() {
//解绑
this.$bus.$off
}
}
</script>
<style scoped>
.weather-icon {
width: 170px;
margin-top: 30px;
}
.weather h1 {
font-size: 80px;
font-weight: 500;
}
.weather h2 {
font-size: 45px;
font-weight: 400;
margin-top: -10px;
}
.details {
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 20px;
margin-top: 50px;
}
.col {
display: flex;
align-items: center;
text-align: left;
}
.col img {
width: 40px;
margin-right: 10px;
}
.humidity,
.wind {
font-size: 28px;
margin-top: -6px;
}
</style>
<template>
<div class="search">
<input type="text" placeholder="请输入城市名字" spellcheck="false" v-model="cityName" @keyup.enter="searchWeather">
<button @click="searchWeather"><img src="../assets/images/search.png"></button>
</div>
</template>
<script>
import axios from 'axios'
export default {
name: 'SearchBOX',
data() {
return {
cityName: ''
}
},
methods: {
searchWeather() {
//开始搜索 发送ajax异步请求
//1.如果输入的名字为空直接返回
if (!this.cityName.trim()) return
// 发送AJAX请求,根据城市的名字获取纬度和经度
const apiKey = "78b262ed7919f0d79a2ca50a4a6f82bf"
const apiUrl = `http://api.openweathermap.org/geo/1.0/direct?q=${this.cityName}&appid=${apiKey}`
axios.get(apiUrl).then(
response => {
console.log('响应数据', response.data)
if (!response.data.length) {
// 触发事件,传递数据给Weather组件
this.$bus.$emit('displayNotFound', true)
} else {
//有数据
// 获取纬度和经度
const lat = response.data[0].lat
console.log('纬度', lat)
const lon = response.data[0].lon
console.log('经度', lon)
// 再发送一次AJAX请求,调用接口,根据纬度和经度获取天气信息
const apiUrlGetWeather = `https://api.openweathermap.org/data/2.5/weather?lat=${lat}&lon=${lon}&appid=${apiKey}&units=metric`
axios.get(apiUrlGetWeather).then(
response => {
console.log('响应数据', response.data)
// 从响应的数据当中获取我们需要的信息:温度、湿度、风速、天气图标
// 将获取到的需要的数据封装成一个weather对象,传递给Weather组件
const weather = {
// 天气图片路径
imgPath: `https://openweathermap.org/img/wn/${response.data.weather[0].icon}@2x.png`,
// 温度
temp: response.data.main.temp,
// 湿度
humidity: response.data.main.humidity,
// 风速
windSpeed: response.data.wind.speed,
// 城市名
city: this.cityName,
// 是否展示Weather组件
isShow: true
}
// 触发事件(使用全局事件总线),传递数据
this.$bus.$emit('displayWeather', weather, false)
},
error => { console.log('错误信息', error.message) }
)
}
},
error => {
console.log('错误信息', error.message)
}
)
}
}
}
</script>
<style scoped>
.search {
width: 100%;
display: flex;
align-items: center;
justify-content: space-between;
}
.search input {
border: 0;
outline: 0;
background: #ebfffc;
color: #555;
padding: 10px 25px;
height: 60px;
border-radius: 30px;
flex: 1;
margin-right: 16px;
font-size: 18px;
}
.search button {
border: 0;
outline: 0;
background: #ebfffc;
border-radius: 50%;
width: 60px;
height: 60px;
cursor: pointer;
}
.search button img {
width: 16px;
}
</style>
main 中开启全局总线
import Vue from 'vue'
import App from './App.vue'
Vue.config.productionTip = false
new Vue({
render: h => h(App),
//开启全局总线
beforeCreate(){
Vue.prototype.$bus = this //this就是vm
}
}).$mount('#app')