微信小程序體驗(yàn)并構(gòu)建自己的微信小程序——Lite天氣

小程序已經(jīng)出來很久了肾档,最近又在學(xué)習(xí)JavaScript,而小程序的開發(fā)語(yǔ)言也是基于JavaScript,所以就打算學(xué)習(xí)一下微信小程序開發(fā)椎例。
大家可以在微信小程序里搜搜索Lite天氣即可體驗(yàn)。

原理

微信小程序的原理印颤,看一下微信官方的文檔寫到:

三端的腳本執(zhí)行環(huán)境聚以及用于渲染非原生組件的環(huán)境是各不相同的:

  • 在 iOS 上您机,小程序的 javascript 代碼是運(yùn)行在 JavaScriptCore 中,是由 WKWebView 來渲染的,環(huán)境有 iOS8际看、iOS9咸产、iOS10
  • 在 Android 上,小程序的 javascript 代碼是通過 X5 JSCore來解析仲闽,是由 X5 基于 Mobile Chrome 53 內(nèi)核來渲染的
  • 在 開發(fā)工具上脑溢, 小程序的 javascript 代碼是運(yùn)行在 nwjs 中,是由 Chrome Webview 來渲染的

據(jù)我猜測(cè)赖欣,我覺得微信小程序能夠提供如此完整的API屑彻,并且性能也有如此之好的體驗(yàn),其原理應(yīng)該是和React Native的原理類似顶吮,通過微信自己的JavaScript運(yùn)行引擎社牲,最終將其中的代碼翻譯成Native的原生控件并展示出來,以達(dá)到媲美原生APP的性能以及用戶體驗(yàn)悴了。

再說開發(fā)工具搏恤,文中提到了nw.js,這個(gè)nwjs據(jù)我所知就是node.js與Browser運(yùn)行時(shí)的合并湃交,據(jù)我所知這個(gè)nw.js就是一個(gè)專門用于跨平臺(tái)開發(fā)的工程熟空,其可利用node.js訪問系統(tǒng)原生的API。但是經(jīng)過我google搞莺,我發(fā)現(xiàn)現(xiàn)在有一個(gè)叫做Electron的項(xiàng)目比nw.js更為火熱息罗,其中atom和vscode也是基于Electron開發(fā)的。至于微信為什么采用nw.js開發(fā)腮敌,我也是不是很了解阱当。

其中大概的原理就講到這里,有興趣的可以參考一下文章

  1. 微信小程序底層的實(shí)現(xiàn)原理是怎樣的糜工?
  2. 微信小程序剖析 | 運(yùn)行機(jī)制及框架原理

開發(fā)準(zhǔn)備

我這里就不過多介紹微信小程序的詳細(xì)教程弊添,因?yàn)槲⑿盘峁┑?a target="_blank" rel="nofollow">官方文檔已經(jīng)十分詳細(xì)地介紹了微信小程序的文件類型、項(xiàng)目結(jié)構(gòu)框架捌木、具體API油坝。

不過我建議在編寫微信小程序之前應(yīng)該要有一下的基礎(chǔ):

  1. JavaScript基礎(chǔ),node.js刨裆、ES6基礎(chǔ)
  2. XML文件澈圈、Html文件基礎(chǔ)、CSS基礎(chǔ)
  3. 了解flex布局

有了以上的基礎(chǔ)知識(shí)帆啃,在官方文檔的指導(dǎo)下瞬女,絕對(duì)能夠快速地進(jìn)行小程序的開發(fā)。

項(xiàng)目實(shí)戰(zhàn)

項(xiàng)目結(jié)構(gòu)

現(xiàn)在只開發(fā)了一個(gè)簡(jiǎn)單的天氣頁(yè)面努潘,因此只寫了index頁(yè)面建立了weather相關(guān)的頁(yè)面诽偷。

項(xiàng)目結(jié)構(gòu)

app.js

這個(gè)文件相當(dāng)于Android 程序中的application坤学,整個(gè)程序只有一個(gè)app.js到單例,因此程序的各種生命周期的回調(diào)都在這里报慕,并且可以存儲(chǔ)一下程序的全局?jǐn)?shù)據(jù)以及變量深浮,例如用戶數(shù)據(jù)等。

App({
  onLaunch: function () {
    
  },
  onShow: () => {
    console.log('onshow');
  },
  onHide: () => {
    console.log('onHide');
  },
  getUserInfo: function (cb) {
    var that = this
    if (this.globalData.userInfo) {
      typeof cb == "function" && cb(this.globalData.userInfo)
    } else {
      //調(diào)用登錄接口
      wx.login({
        success: function () {
          wx.getUserInfo({
            success: function (res) {
              that.globalData.userInfo = res.userInfo
              typeof cb == "function" && cb(that.globalData.userInfo)
            }
          })
        }
      })
    }
  },
  globalData: {
    userInfo: null
  }
})

app.json:

這個(gè)相當(dāng)于是程序的路由表以及配置表眠冈,包括程序的頁(yè)面注冊(cè)飞苇、網(wǎng)絡(luò)配置、底部導(dǎo)航欄蜗顽、頂部導(dǎo)航欄的配置都可以在這里編寫布卡,具體的可以在官方文檔里進(jìn)行查看。

{
  "pages": [
    "pages/weather/index/weather",
    "pages/weather/city/city",
    "pages/weather/detail/detail",
    "pages/weather/setting/setting"
  ],
  "window": {
    "backgroundTextStyle": "light",
    "navigationBarBackgroundColor": "#09bb07",
    "navigationBarTitleText": "Lite天氣",
    "navigationBarTextStyle": "white",
    "enablePullDownRefresh": true
  },
  "tabBar": {
    "list": [
      {
        "pagePath": "pages/weather/index/weather",
        "text": "天氣",
        "iconPath": "/resources/weather_icon_normal.png",
        "selectedIconPath": "/resources/weather_icon_selected.png"
      },
      {
        "pagePath": "pages/weather/setting/setting",
        "text": "我的",
        "iconPath": "/resources/setting_icon_normal.png",
        "selectedIconPath": "/resources/setting_icon_selected.png"
      }
    ],
    "color": "#dbdbdb",
    "selectedColor": "#09bb07",
    "backgroundColor": "#ffffff",
    "borderStyle": "black"
  },
  "networkTimeout": {
    "request": 5000,
    "connectSocket": 20000,
    "uploadFile": 20000,
    "downloadFile": 20000
  }
}

之前都是app的全局配置诫舅,現(xiàn)在來編寫具體的頁(yè)面羽利。

預(yù)期的頁(yè)面是這個(gè)樣子的設(shè)計(jì)。

天氣界面

weather.wxml:

<view class="container">
  <image src="{{backgroudUrl}}" mode="scaleToFill"></image>
  <view class="header">
    <view class="header-top">
      <view id="city">{{weather.city}}</view>
      <view>{{weather.update}}</view>
    </view>
    <view class="header-condition">
      <view id="temp">{{weather.now.tmp}}℃</view>
      <view>{{weather.now.cond.txt}}</view>
    </view>
  </view>
  <view class="item-list" wx:for="{{weather.daily}}">
    <view class="daily-item">
      <view class="item-date">{{item.date}}</view>
      <view class="item-date">{{item.cond.txt_d}}</view>
      <view class="item-date">{{item.tmp.max}}</view>
      <view class="item-date">{{item.tmp.min}}</view>
    </view>
  </view>
  <view class="air-list">
    <view class="air-item">
      <view>{{weather.aqi.qlty}}</view>
      <view>空氣質(zhì)量</view>
    </view>
    <view class="air-item">
      <view>{{weather.aqi.aqi}}</view>
      <view>AQI</view>
    </view>
    <view class="air-item">
      <view>{{weather.aqi.pm25}}</view>
      <view>PM2.5</view>
    </view>
    <view class="air-item">
      <view>{{weather.aqi.pm10}}</view>
      <view>PM10</view>
    </view>
    <view class="air-item">
      <view>{{weather.now.hum}}%</view>
      <view>濕度</view>
    </view>
  </view>
  <view class="life-suggestion">
    <text>空氣指數(shù):{{weather.suggestion.air.brf}},{{weather.suggestion.air.txt}}</text>
    <text>舒適度指數(shù):{{weather.suggestion.comf.brf}},{{weather.suggestion.comf.txt}}</text>
    <text>洗車指數(shù):{{weather.suggestion.cw.brf}},{{weather.suggestion.cw.txt}}</text>
    <text>穿衣指數(shù):{{weather.suggestion.drsg.brf}},{{weather.suggestion.drsg.txt}}</text>
    <text>感冒指數(shù):{{weather.suggestion.flu.brf}},{{weather.suggestion.flu.txt}}</text>
    <text>運(yùn)動(dòng)指數(shù):{{weather.suggestion.sport.brf}},{{weather.suggestion.sport.txt}}</text>
    <text>旅游指數(shù):{{weather.suggestion.trav.brf}},{{weather.suggestion.trav.txt}}</text>
    <text>紫外線指數(shù):{{weather.suggestion.uv.brf}},{{weather.suggestion.uv.txt}}</text>
  </view>
</view>

類似于css的可以設(shè)置在weather.wxss

.container {
  height: 100%;
  width: 100%;
  display: flex;
  flex-direction: column;
}


image {
  width: 100%;
  height: 250%;
  filter: blur(1px);
  position: absolute;
  z-index: -1;
}

.header {
  padding: 20rpx;
  height: 400rpx;
  display: flex;
  justify-content: space-between;
  flex-direction: column;
  margin-bottom: 20rpx;
}

.header-top {
  display: flex;
  flex-direction: row;
  justify-content: space-between;
}

.header-condition {
  padding: 20rpx;
  display: flex;
  align-self: flex-end;
  align-items: center;
  flex-direction: column;
  justify-content: flex-end;
}

#temp {
  color: #fff;
  margin-bottom: 20rpx;
  font-size: 100rpx;
}

.header view {
  color: #fff;
  font-size: 30rpx;
}

.item-list {
  padding: 20rpx;
  margin-left: 40rpx;
  margin-right: 40rpx;
  background: rgba(0, 0, 0, 0.2);
  border-radius: 3rpx;
}

.daily-item {
  font-size: 30rpx;
  color: white;
  display: flex;
  flex-direction: row;
  justify-content: space-around;
}

.air-list {
  margin-left: 40rpx;
  margin-right: 40rpx;
  margin-top: 60rpx;
  margin-bottom: 40rpx;
  display: flex;
  height: 100px;
  color: white;
  font-size: 30rpx;
  align-items: center;
  flex-direction: row;
  justify-content: space-around;
  background: rgba(0, 0, 0, 0.2);
  border-radius: 3rpx;
}

.air-item {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
}

.air-item view {
  margin: 20rpx;
}

.life-suggestion {
  color: white;
  padding: 50rpx;
  font-size: 30rpx;
  margin-left: 40rpx;
  margin-right: 40rpx;
  margin-bottom: 40rpx;
  display: flex;
  flex-direction: column;
  background: rgba(0, 0, 0, 0.2);
  border-radius: 3rpx;
}

.life-suggestion text {
  margin-top: 20rpx;
  font-style: oblique;
}

weather.js

最后就是頁(yè)面的數(shù)據(jù)的獲取以及相應(yīng)的邏輯處理:

const weatherUtil = require('../../../utils/weatherUtil.js');
const imageUtil=require('../../../utils/imageUtil.js');
var app = getApp();

function refreshData(that) {
  weatherUtil.loadWeatherData((success, data) => {
    that.setData({
      weather: data
    });
    wx.stopPullDownRefresh();
  });
}

Page({
  data: {
    title: 'Lite天氣',
    weather: {},
    backgroudUrl:''
  },

  bindViewTap: function () {

  },

  onLoad: function () {
    var that=this;
    imageUtil.requestDailyImageUrl((url)=>{
        that.setData({
          backgroudUrl:url
        });
    });
    refreshData(that);
  },

  onPullDownRefresh: function () {
    refreshData(this);
  }
})

我將獲取位置以及一些數(shù)據(jù)都封裝在了weatherUtil里面,這個(gè)天氣API是和風(fēng)天氣提供的刊懈,可以自己去和風(fēng)天氣官網(wǎng)申請(qǐng)key值:

const baseUrl = 'https://free-api.heweather.com/v5/weather?key=';
const app = getApp();

/**
 * 根據(jù)經(jīng)緯度獲取天氣
 */
function requestWeatherByLocation(latitude, longitude, callback) {
    wx.request({
        url: baseUrl + '&city=' + longitude + ',' + latitude,
        data: {},
        method: 'GET', // OPTIONS, GET, HEAD, POST, PUT, DELETE, TRACE, CONNECT
        // header: {}, // 設(shè)置請(qǐng)求的 header
        success: function (res) {
            // success
            var result = pareseWeahterData(res);
            callback(true, result);
        },
        fail: function (res) {
            // fail
            callback(false);
        }
    });
}

/**
 * 獲取天氣回調(diào)
 */
function requestWeatherData(callback) {
    requestLocation((success, latitude, longitude) => {
        if (success == false) {
            latitude = 120.343;
            longitude = 36.088;
        }
        requestWeatherByLocation(latitude, longitude, callback);
    });
}

/**
 * 解析數(shù)據(jù)
 */
function pareseWeahterData(orign) {
    var weather = {};
    console.log(orign);
    var data = orign.data.HeWeather5[0];
    weather.city = data.basic.city;
    weather.now = data.now;
    weather.daily = data.daily_forecast;
    weather.suggestion = data.suggestion;
    weather.basic = data.basic;
    weather.update = data.basic.update.loc.substring(10, 16);
    weather.aqi=data.aqi.city;
    console.log(weather);
    return weather;
}

/**
 * 獲取位置信息这弧,返回經(jīng)緯度
 */
function requestLocation(callback) {
    wx.getLocation({
        type: 'wgs84', // 默認(rèn)為 wgs84 返回 gps 坐標(biāo),gcj02 返回可用于 wx.openLocation 的坐標(biāo)
        success: function (res) {
            callback(true, res.latitude, res.longitude);
        },
        fail: function (res) {
            callback(false);
        }
    });
}

function loadWeatherData(callback) {
    requestWeatherData(callback);
}

module.exports = { loadWeatherData: loadWeatherData }

ok虚汛,以上就是一個(gè)簡(jiǎn)單的天氣頁(yè)面的開發(fā)匾浪。

總之,按照官方文檔的指導(dǎo)卷哩,很輕松就能夠制作一個(gè)簡(jiǎn)單的微信小程序蛋辈。

總結(jié)

通過開發(fā)這個(gè)簡(jiǎn)答的天氣小程序,收獲了不少将谊,但是也不得不吐槽一下微信小程序的設(shè)計(jì)冷溶。

  1. 開發(fā)十分簡(jiǎn)單,只要掌握簡(jiǎn)單的JavaScript基礎(chǔ)就能夠快速開發(fā)尊浓。
  2. 提供了較為完整的組件以及各種API
  3. API設(shè)計(jì)比較蛋疼逞频,有些設(shè)計(jì)得不太好。
  4. 在程序里使用網(wǎng)絡(luò)請(qǐng)求需要進(jìn)行指定對(duì)應(yīng)的域名栋齿,否則不能夠訪問苗胀。
  5. 程序的提交審核比較快,我的大概是用了一天的時(shí)間就申請(qǐng)好了瓦堵。

下一個(gè)研究的就是ReactNative基协,之后會(huì)用RN開發(fā)一個(gè)Lite天氣。
項(xiàng)目源碼:https://github.com/nickming/WXLiteWeather
歡迎star

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末菇用,一起剝皮案震驚了整個(gè)濱河市澜驮,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌惋鸥,老刑警劉巖泉唁,帶你破解...
    沈念sama閱讀 218,858評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件鹅龄,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡亭畜,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,372評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門迎卤,熙熙樓的掌柜王于貴愁眉苦臉地迎上來拴鸵,“玉大人,你說我怎么就攤上這事蜗搔【⒚辏” “怎么了?”我有些...
    開封第一講書人閱讀 165,282評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵樟凄,是天一觀的道長(zhǎng)聘芜。 經(jīng)常有香客問我,道長(zhǎng)缝龄,這世上最難降的妖魔是什么汰现? 我笑而不...
    開封第一講書人閱讀 58,842評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮叔壤,結(jié)果婚禮上瞎饲,老公的妹妹穿的比我還像新娘。我一直安慰自己炼绘,他們只是感情好嗅战,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,857評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著俺亮,像睡著了一般驮捍。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上脚曾,一...
    開封第一講書人閱讀 51,679評(píng)論 1 305
  • 那天东且,我揣著相機(jī)與錄音,去河邊找鬼斟珊。 笑死苇倡,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的囤踩。 我是一名探鬼主播旨椒,決...
    沈念sama閱讀 40,406評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼堵漱!你這毒婦竟也來了综慎?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,311評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤勤庐,失蹤者是張志新(化名)和其女友劉穎示惊,沒想到半個(gè)月后好港,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,767評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡米罚,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,945評(píng)論 3 336
  • 正文 我和宋清朗相戀三年钧汹,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片录择。...
    茶點(diǎn)故事閱讀 40,090評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡拔莱,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出隘竭,到底是詐尸還是另有隱情塘秦,我是刑警寧澤,帶...
    沈念sama閱讀 35,785評(píng)論 5 346
  • 正文 年R本政府宣布动看,位于F島的核電站尊剔,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏菱皆。R本人自食惡果不足惜须误,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,420評(píng)論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望搔预。 院中可真熱鬧霹期,春花似錦、人聲如沸拯田。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,988評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)船庇。三九已至吭产,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間鸭轮,已是汗流浹背臣淤。 一陣腳步聲響...
    開封第一講書人閱讀 33,101評(píng)論 1 271
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留窃爷,地道東北人邑蒋。 一個(gè)月前我還...
    沈念sama閱讀 48,298評(píng)論 3 372
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像按厘,于是被迫代替她去往敵國(guó)和親医吊。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,033評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,163評(píng)論 25 707
  • 你也在玩小程序?這些基本原理你知道嗎? 微信小程序使用了前端技術(shù)棧JavaScript/WXML/WXSS逮京。...
    奮斗的憤青i閱讀 2,143評(píng)論 0 4
  • 突然發(fā)現(xiàn)這哥們很牛……無它……
    逗霸君閱讀 221評(píng)論 0 2
  • 在兒童樂園當(dāng)管理員的時(shí)候草描,我每天都會(huì)看到很多可愛的小朋友览绿。有一天一個(gè)大約8,9歲的小女孩吸引了我的注意穗慕。 她在父母...
    陸艷如閱讀 353評(píng)論 0 0
  • 【讀書心語(yǔ)】遇見從美好開始饿敲。每次遇見都在人生劇本上增添了一些劇本題材和劇情章節(jié),我們有時(shí)是主角有時(shí)是配角逛绵,因?yàn)槊看?..
    佛前的那朵青蓮閱讀 126評(píng)論 0 0