前言
Uniapp作为一个使用Vue.js语法开发跨平台应用的前端框架,近年来受到了广泛关注。它允许开发者编写一套代码,同时发布到iOS、Android、Web以及各种小程序平台,大大提高了开发效率。本文将通过一个完整的天气预报应用案例,详细介绍Uniapp的开发流程和关键技术点。
项目概述
我们将开发一个具备以下功能的天气预报应用:
- 获取用户当前位置
- 显示当前天气情况和未来5天预报
- 支持城市搜索功能
- 温度单位切换(摄氏度/华氏度)
- 多平台适配(iOS、Android、微信小程序)
环境准备与项目创建
首先确保已安装HBuilder X,这是官方推荐的Uniapp开发工具。
创建新项目
打开HBuilder X,选择”文件”->”新建”->”项目”,选择Uniapp项目模板,填写项目名称”WeatherApp”,选择Vue3版本(本文基于Vue3 Composition API)。
项目结构说明
WeatherApp/
├── pages/ // 页面文件
│ └── index/ // 首页
├── static/ // 静态资源
├── components/ // 自定义组件
├── store/ // 状态管理
├── utils/ // 工具函数
└── manifest.json // 应用配置
核心功能实现
1. 获取用户位置
使用Uniapp的地理位置API获取用户当前坐标:
// utils/location.js
export const getCurrentLocation = () => {
return new Promise((resolve, reject) => {
uni.getLocation({
type: 'wgs84',
success: (res) => {
resolve({
latitude: res.latitude,
longitude: res.longitude
})
},
fail: (err) => {
reject(err)
}
})
})
}
2. 调用天气API
我们将使用OpenWeatherMap API获取天气数据(需注册获取API key):
// api/weather.js
const API_KEY = 'your_api_key'
const BASE_URL = 'https://api.openweathermap.org/data/2.5'
export const getCurrentWeather = async (lat, lon) => {
try {
const response = await uni.request({
url: `${BASE_URL}/weather?lat=${lat}&lon=${lon}&appid=${API_KEY}&units=metric`
})
return response.data
} catch (error) {
console.error('获取当前天气失败:', error)
throw error
}
}
export const getForecast = async (lat, lon) => {
try {
const response = await uni.request({
url: `${BASE_URL}/forecast?lat=${lat}&lon=${lon}&appid=${API_KEY}&units=metric`
})
return response.data
} catch (error) {
console.error('获取天气预报失败:', error)
throw error
}
}
3. 状态管理
使用Pinia进行状态管理(Uniapp官方推荐):
// store/weather.js
import { defineStore } from 'pinia'
export const useWeatherStore = defineStore('weather', {
state: () => ({
currentWeather: null,
forecast: [],
currentCity: '未知位置',
unit: 'celsius' // 或 'fahrenheit'
}),
actions: {
async fetchWeather(lat, lon) {
try {
const [current, forecast] = await Promise.all([
getCurrentWeather(lat, lon),
getForecast(lat, lon)
])
this.currentWeather = current
this.forecast = this.processForecast(forecast.list)
this.currentCity = current.name
} catch (error) {
uni.showToast({
title: '获取天气信息失败',
icon: 'none'
})
}
},
processForecast(forecastList) {
// 处理5天预报数据,按天分组
const dailyForecast = {}
forecastList.forEach(item => {
const date = item.dt_txt.split(' ')[0]
if (!dailyForecast[date]) {
dailyForecast[date] = item
}
})
return Object.values(dailyForecast).slice(0, 5)
},
toggleUnit() {
this.unit = this.unit === 'celsius' ? 'fahrenheit' : 'celsius'
}
},
getters: {
displayTemperature: (state) => (temp) => {
if (state.unit === 'celsius') {
return `${Math.round(temp)}°C`
} else {
return `${Math.round(temp * 9/5 + 32)}°F`
}
}
}
})
页面设计与实现
主页面布局
{{ currentCity }}
{{ displayTemperature(currentWeather.main.temp) }}
{{ currentWeather.weather[0].description }}
湿度: {{ currentWeather.main.humidity }}%
风速: {{ currentWeather.wind.speed }} m/s
5天预报
{{ formatDate(item.dt) }}
{{ displayTemperature(item.main.temp_max) }} /
{{ displayTemperature(item.main.temp_min) }}
{{ item.weather[0].main }}
import { ref, onMounted } from 'vue'
import { useWeatherStore } from '@/store/weather'
import { getCurrentLocation } from '@/utils/location'
const weatherStore = useWeatherStore()
const { currentWeather, forecast, currentCity, unit, displayTemperature } = storeToRefs(weatherStore)
onMounted(() => {
loadWeather()
})
const loadWeather = async () => {
try {
const location = await getCurrentLocation()
await weatherStore.fetchWeather(location.latitude, location.longitude)
} catch (error) {
uni.showToast({
title: '获取位置失败',
icon: 'none'
})
}
}
const searchCity = async (keyword) => {
// 实现城市搜索功能
// 这里可以调用地理编码API将城市名转换为坐标
}
const toggleUnit = () => {
weatherStore.toggleUnit()
}
const formatDate = (timestamp) => {
// 日期格式化逻辑
}
样式设计要点
虽然本文不使用style标签,但实际开发中需要注意:
- 使用flex布局实现响应式设计
- 为不同平台设计差异化样式(使用条件编译)
- 注意iOS和Android的平台特性差异
- 使用rpx单位确保多端尺寸适配
多平台适配与发布
条件编译
Uniapp支持条件编译,可以针对不同平台编写特定代码:
// #ifdef MP-WEIXIN
console.log('这是微信小程序平台')
// #endif
// #ifdef APP-PLUS
console.log('这是App平台')
// #endif
// #ifdef H5
console.log('这是H5平台')
// #endif
平台特定配置
在manifest.json中配置各平台特定设置:
{
"appid": "your_appid",
"h5": {
"title": "天气预报应用"
},
"mp-weixin": {
"appid": "weixin_appid",
"setting": {
"urlCheck": false
}
}
}
应用发布
发布到不同平台:
- 微信小程序: 运行”发行->小程序-微信”,生成生产版代码
- App: 配置证书后选择”发行->原生App-云打包”
- H5: 选择”发行->网站-H5手机版”
性能优化建议
- 使用图片懒加载减少初始加载时间
- 合理使用缓存策略,减少API调用次数
- 按需引入组件,减小包体积
- 使用subNVue原生渲染提升复杂页面性能
- 优化首屏加载,使用骨架屏提升用户体验
常见问题与解决方案
1. 地理位置获取失败
解决方案:添加手动选择城市功能作为备选方案
2. API调用限制
解决方案:实现本地缓存机制,避免频繁调用API
3. 多平台样式差异
解决方案:使用条件编译针对不同平台调整样式
结语
通过这个天气预报应用的开发实践,我们展示了Uniapp在跨平台开发中的强大能力。从API调用到状态管理,从页面设计到多平台发布,Uniapp提供了一站式解决方案。希望本文能帮助你快速掌握Uniapp开发技能,构建出优秀的跨平台应用。
完整的项目代码已上传至GitHub,欢迎Star和Fork:https://github.com/example/weather-app

