这次我就带大家开发一个功能齐全的微信小程序,希望对大家有一些参考价值。
这次让我们一起开发一个天气预报小程序。选择这种类型有两个原因。第一,天气小程序整体复杂度比较低,适合我们讲解问题。此外,这种类型的应用也更适合微信小程序生态的场景。我的理解是,这种生态不适合开发过于复杂的应用。所以选择一种类型。我们先来看看最终的效果,并有一个感官上的理解:
这是我的调试器的最终运行效果,它根据您当前的位置显示当前和未来的天气情况。对于小程序的使用场景,我个人认为更适合。
:首先给大家展示一下操作效果,设置一个感官感知。然后,我们可以开始了。首先,在微信开发者工具中创建一个项目:
接下来,在项目创建窗口中,有一点解释。在AppID条目中,如果您已经有一个内部测试帐户,请填写您的AppID。如果没有内测账号,点击旁边的No AppID(相信大部分同学都没有内测账号,可以用这个方法继续本地调试)。
小程序的基本流程,以及项目结构,请参考我们之前的文章,会给大家展示没有内测账号的微信小程序的完整开发过程。我们在这里不讨论基础知识的细节。
整个项目的文件结构如下:
如您所见,主页上有一个索引目录。App.js是程序的主入口,utils.js是我们读取天气数据的工具脚本。还有一个bg.jpg的图片文件,是小程序的背景图。
这个项目的所有文件都在这里,不是很简单吗?对于项目的完整生成,您可以在我们的Github主页上查看https://github.com/swiftcafex/wechat-weather。
介绍了基本结构,然后我们就可以开始编码了。对于这个天气程序,首先要处理的是天气数据的获取。那我们就一步一步来。
首先,我们需要得到当前的地理位置。微信为我们提供了相应的界面。我们可以在util.js中定义这样一个方法:
函数getLocation(回调){ 0
wx . GetLocation({ 0
成功:功能(RES){ 0
回调(真、res .纬度、res .经度);
},
fail:函数(){ 0
回调(假);
}
})
}
wx.getLocation方法返回我们当前位置的经纬度信息。如果成功,我们将返回信息进行回调;如果不成功,我们将返回false进行回调。请注意,故障情况需要在实际开发中处理。例如,如果一些用户没有打开位置的权限,并且无法处理,可能会出现意外情况。
得到现在的职位后,还应该得到什么?天气数据。有很多相关的API,我们的小程序使用的是darksky.net提供的天气API。它提供了一个非常简单的API接口:
函数getWeatherByLocation(纬度、经度、回调){ 0
应用编程接口密钥=“您自己的密钥”;
var APiURl=' https://API . dark sky . net/forecast/' APiKey '/'纬度','经度'?lang=zh
amp;units=ca";wx.request({
url: apiURL,
success: function(res){
var weatherData = parseWeatherData(res.data);
getCityName(latitude, longitude, function(city){
weatherData.city = city;
callback(weatherData);
});
}
});
}
getWeatherByLocation 这个方法依然写在 util.js 里面,它的逻辑也很简单,拼接出 darksky 的 API 的 URL,然后调用 wx.request 请求网络数据。 因为我们不需要用到 API 返回的所有数据, 只需要获得当天的天气,以及未来 7 天的预报即可。 所以这里还使用 parseWeatherData 方法取得我们需要的数据并重组成新的结果。 这个方法的定义如下:
function parseWeatherData(data) {
var weather = {};
weather["current"] = data.currently;
weather["daily"] = data.daily;
return weather;
}
从上面的代码不难看出,我们只取得了原始结果集的 currently 和 daily 数据,然后重新返回。 为什么我们要这样取得部分数据呢,主要是因为这个接口的其他数据我们并不需要,所以就没必要再传给应用层了。 原始数据的格式给大家贴一下:
大家可能注意到了,这个 API 给我们返回的数据中,有些数据的格式我们还需要继续处理一下。 比如 time 是用时间戳的形式给我们返回的,但我们需要将时间显示在 UI 上, 所以我们就需要进行一下格式转换。 另外 temperature 字段的格式也不是我们需要的。温度数据我们不需要显示到小数点之后,取整数就可以。
定义几个格式化数据的方法:
//将时间戳格式化为日期
function formatDate(timestamp) {
var date = new Date(timestamp * 1000);
return date.getMonth()+1 + "月" + date.getDate() + "日 " + formatWeekday(timestamp);
}
//将时间戳格式化为时间
function formatTime(timestamp) {
var date = new Date(timestamp * 1000);
return date.getHours() + ":" + date.getMinutes();
}
//中文形式的每周日期
function formatWeekday(timestamp) {
var date = new Date(timestamp * 1000);
var weekday = ["周日", "周一", "周二", "周三", "周四", "周五", "周六"];
var index = date.getDay();
return weekday[index];
}
这三个方法都是对日期进行格式化输出。具体功能代码里的注释已经说明了,不多赘述。 最后,我们把前面所有的方法整合起来,组成给应用层的接口:
//加载天气数据
function requestWeatherData(cb) {
getLocation(function(success, latitude, longitude){
//如果 GPS 信息获取不成功, 设置一个默认坐标
if(success == false) {
latitude = 39.90403;
longitude = 116.407526;
}
//请求天气数据 API
getWeatherByLocation(latitude, longitude, function(weatherData){
cb(weatherData);
});
});
}
请求原始数据,这里调用了 getLocation 请求当前位置, 在回调里面判断返回结果是否获取位置成功,如果不成功,设置一个默认位置。 这个判断在实际的产品中还是比较有用的。 位置获取不成功的情况还是比较多的。比如用户没有开启定位权限。
紧接着,在里面又调用了 getWeatherByLocation 方法获取天气数据,然后将原始的天气数据返回。
原始数据读取成功后, 我们再封装一层,将原始数据进行加工:
function loadWeatherData(callback) {
requestWeatherData(function(data){
//对原始数据做一些修整, 然后输出给前端
var weatherData = {};
weatherData = data;
weatherData.current.formattedDate = formatDate(data.current.time);
weatherData.current.formattedTime = formatTime(data.current.time);
weatherData.current.temperature = parseInt(weatherData.current.temperature);
var wantedDaily = [];
for(var i = 1;i < weatherData.daily.data.length;i++) {
var wantedDailyItem = weatherData.daily.data[i];
var time = weatherData.daily.data[i].time;
wantedDailyItem["weekday"] = formatWeekday(time);
wantedDailyItem["temperatureMin"] = parseInt(weatherData.daily.data[i]["temperatureMin"])
wantedDailyItem["temperatureMax"] = parseInt(weatherData.daily.data[i]["temperatureMax"])
wantedDaily.push(wantedDailyItem);
}
weatherData.daily.data = wantedDaily;
callback(weatherData);
});
}
这是最终输出给应用层的方法,它里面用了咱们刚才定义的几个数据格式化方法将返回的原始天气数据加工了一下。 最终传递给回调方法。
最后我们将这个方法暴露给应用层:
module.exports = {
loadWeatherData: loadWeatherData
}
这个语法和 nodejs 比较相似。 到此为止,咱们这个小程序的数据处理逻辑部分就开发完成了。 大家可以稍微消化一下, 下一篇会和大家一起处理应用层的逻辑。 如果你想查看完整的代码, 也可以进入 Github