前言
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