用 Vue 快速实现一个类似手机天气 App 里简洁的多日预报界面,让刚接触 Vue 的同学能直观理解axios数据请求、数据渲染、列表循环这些基础用法,代码直接生成 HTML 本地浏览。
页面代码已对接天气接口, 会自动展示所在城市的天气数据,
涉及Vue的功能
- 数据渲染
- 列表循环
- axios的使用, 请求了天气api接口, 并解析数据展示
静态资源(图标):用免费图标 CDN 先做演示,实际项目可对接天气 API 动态获取对应天气图标,这里先简化流程。
纯前端实现:不需要后端,写好 HTML、CSS、Vue 逻辑,直接浏览器打开运行,降低学习和实践门槛。
效果预览
下面是完整代码, 复制保存为html文件, 双击打开可以直接看到效果
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>天气预报界面</title>
<style>
body{font-family:sans-serif;margin:0;padding:20px;background-color:#fff}.location{font-size:16px;color:#4caf50;margin-bottom:10px}.date{font-size:14px;color:#999;margin:2px 0 0 10px}.weather-container{display:flex;gap:40px}.weather-item{text-align:center}.weather-item .day{font-size:16px;font-weight:bold;margin-bottom:10px}.weather-icon{width:60px;height:60px;margin-bottom:10px}.temp-range{font-size:16px;margin-bottom:5px}.weather-desc{font-size:14px;color:#666}
</style>
</head>
<body>
<div id="app">
<div style="display: flex;">
<div class="location">{{ city }}</div>
<div class="date" id="date-display"></div>
</div>
<div class="weather-container">
<div class="weather-item" v-for="(item, index) in weatherList" :key="index">
<div class="day">{{ item.week }}</div>
<img :src="item.wea_img" class="weather-icon" alt="{{item.wea_img}}">
<div class="temp-range">{{ item.wea }}</div>
<div class="weather-desc">{{ item.tem2 }}° ~ {{ item.tem1 }}°</div>
</div>
</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.7.14/vue.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/1.4.0/axios.min.js"></script>
<script>
new Vue({
el: '#app',
data: {
city: '',
weatherList: []
},
created() {
this.fetchWeatherData();
},
methods: {
async fetchWeatherData() {
try {
// get接口里使用的appid和key请自行前往天气api注册
const response = await axios.get('http://gfeljm.tianqiapi.com/api?unescape=1&version=v9&appid=55556666&appsecret=12341234');
this.city = response.data.city;
this.weatherList = response.data.data.slice(0, 3);
for(var i = 0; i< 3; i++){
this.weatherList[i].wea_img = 'http://dps.tianqiapi.com/static/skin/apple/' + this.weatherList[i].wea_img + '.png';
}
document.title = response.data.city + '天气'
} catch (error) {
console.error('获取天气数据失败', error);
}
},
viewFull() {
document.location.href='http://tianqiapi.com'
}
}
});
// 农历数据(简化版)
const lunarInfo = [
0x04bd8, 0x04ae0, 0x0a570, 0x054d5, 0x0d260, 0x0d950, 0x16554, 0x056a0, 0x09ad0, 0x055d2,
0x04ae0, 0x0a5b6, 0x0a4d0, 0x0d250, 0x1d255, 0x0b540, 0x0d6a0, 0x0ada2, 0x095b0, 0x14977,
0x04970, 0x0a4b0, 0x0b4b5, 0x06a50, 0x06d40, 0x1ab54, 0x02b60, 0x09570, 0x052f2, 0x04970,
0x06566, 0x0d4a0, 0x0ea50, 0x06e95, 0x05ad0, 0x02b60, 0x186e3, 0x092e0, 0x1c8d7, 0x0c950,
0x0d4a0, 0x1d8a6, 0x0b550, 0x056a0, 0x1a5b4, 0x025d0, 0x092d0, 0x0d2b2, 0x0a950, 0x0b557,
0x06ca0, 0x0b550, 0x15355, 0x04da0, 0x0a5d0, 0x14573, 0x052d0, 0x0a9a8, 0x0e950, 0x06aa0,
0x0aea6, 0x0ab50, 0x04b60, 0x0aae4, 0x0a570, 0x05260, 0x0f263, 0x0d950, 0x05b57, 0x056a0,
0x096d0, 0x04dd5, 0x04ad0, 0x0a4d0, 0x0d4d4, 0x0d250, 0x0d558, 0x0b540, 0x0b5a0, 0x195a6,
0x095b0, 0x049b0, 0x0a974, 0x0a4b0, 0x0b27a, 0x06a50, 0x06d40, 0x0af46, 0x0ab60, 0x09570,
0x04af5, 0x04970, 0x064b0, 0x074a3, 0x0ea50, 0x06b58, 0x055c0, 0x0ab60, 0x096d5, 0x092e0,
0x0c960, 0x0d954, 0x0d4a0, 0x0da50, 0x07552, 0x056a0, 0x0abb7, 0x025d0, 0x092d0, 0x0cab5,
0x0a950, 0x0b4a0, 0x0baa4, 0x0ad50, 0x055d9, 0x04ba0, 0x0a5b0, 0x15176, 0x052b0, 0x0a930,
0x07954, 0x06aa0, 0x0ad50, 0x05b52, 0x04b60, 0x0a6e6, 0x0a4e0, 0x0d260, 0x0ea65, 0x0d530,
0x05aa0, 0x076a3, 0x096d0, 0x04bd7, 0x04ad0, 0x0a4d0, 0x1d0b6, 0x0d250, 0x0d520, 0x0dd45,
0x0b5a0, 0x056d0, 0x055b2, 0x049b0, 0x0a577, 0x0a4b0, 0x0aa50, 0x1b255, 0x06d20, 0x0ada0
];
// 农历月份名称
const lunarMonthNames = ['正', '二', '三', '四', '五', '六', '七', '八', '九', '十', '十一', '腊'];
// 农历日名称
const lunarDayNames = ['初', '十', '廿', '卅'];
const lunarDayNums = ['一', '二', '三', '四', '五', '六', '七', '八', '九', '十'];
// 获取农历日期信息
function getLunarDate(date) {
const year = date.getFullYear();
const month = date.getMonth();
const day = date.getDate();
// 计算从1900年到目标年份的总天数
let totalDays = 0;
for (let y = 1900; y < year; y++) {
totalDays += isLeapYear(y) ? 366 : 365;
}
// 计算当年的天数
for (let m = 0; m < month; m++) {
totalDays += getDaysInMonth(year, m);
}
totalDays += day;
// 计算农历日期
let lunarYear = 1900;
let days = 0;
let leapMonth = 0;
let isLeap = false;
while (true) {
const yearInfo = lunarInfo[lunarYear - 1900];
leapMonth = (yearInfo & 0xf0000) >> 16;
days = 348; // 基本天数
// 计算每月天数
for (let i = 0x8000; i > 0x8; i >>= 1) {
days += (yearInfo & i) ? 1 : 0;
}
// 计算闰月天数
if (leapMonth > 0) {
days += (yearInfo & 0x10000) ? 30 : 29;
}
if (totalDays <= days) break;
totalDays -= days;
lunarYear++;
}
// 计算农历月份和日期
let lunarMonth = 1;
let lunarDay = totalDays;
const yearInfo = lunarInfo[lunarYear - 1900];
leapMonth = (yearInfo & 0xf0000) >> 16;
// 计算每个月的天数,直到找到对应的月份
for (let i = 0x8000; i > 0x8; i >>= 1) {
const monthDays = (yearInfo & i) ? 30 : 29;
if (lunarDay <= monthDays) break;
lunarDay -= monthDays;
lunarMonth++;
}
// 处理闰月
if (leapMonth > 0) {
let leapDays = (yearInfo & 0x10000) ? 30 : 29;
if (lunarMonth === leapMonth + 1 && !isLeap) {
isLeap = true;
lunarMonth--;
} else if (isLeap) {
if (lunarDay > leapDays) {
lunarDay -= leapDays;
lunarMonth++;
isLeap = false;
}
}
}
// 转换农历日为中文表示
let lunarDayName = '';
if (lunarDay === 20) {
lunarDayName = '二十';
} else if (lunarDay === 30) {
lunarDayName = '三十';
} else {
const d = lunarDay % 10;
const p = Math.floor(lunarDay / 10);
lunarDayName = lunarDayNames[p] + lunarDayNums[d - 1];
}
// 转换农历月为中文表示
let lunarMonthName = lunarMonthNames[lunarMonth - 1];
if (isLeap) lunarMonthName = '闰' + lunarMonthName;
return {
year: lunarYear,
month: lunarMonth,
day: lunarDay,
monthName: lunarMonthName,
dayName: lunarDayName
};
}
// 判断是否为闰年
function isLeapYear(year) {
return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0;
}
// 获取月份天数
function getDaysInMonth(year, month) {
const days = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
if (month === 1 && isLeapYear(year)) {
return 29;
}
return days[month];
}
// 更新日期显示
function updateDateDisplay() {
const now = new Date();
const month = now.getMonth() + 1;
const day = now.getDate();
const lunarDate = getLunarDate(now);
document.getElementById('date-display').textContent = `${month}月${day}日` + `农历${lunarDate.monthName}月${lunarDate.dayName}`;
}
// 页面加载时更新日期
document.addEventListener('DOMContentLoaded', updateDateDisplay);
</script>
</body>
</html>