去年年末 o2 開源了 Taro,一直手癢癢沒去玩。考慮到 wx 的審覈制度,因此決定寫個工具類小程序。趕在 Taro 喜提第 2000 個 issues 之際,Natsuha 也終於上線了。源碼所有釋出(除涉及私鑰部分,GitHub有說明),文章後面會貼出一些仍需優化的點,歡迎你們一塊兒討論。
Natsuha Weather 已開源,歡迎你們一塊兒折騰,給個 star 也是極好的~ GitHub Repocss
技術棧是 Taro + mobx + TypeScript
,接口來自 Yahoo Weather API,固然設計也是參 (chao) 考 (xi) 的 Yahoo Weather. 接口有時會訪問失敗,尤爲是晚上,我也沒辦法啊。🤷html
因爲衆所周知的緣由,wx 小程序沒法調用未 bei an 的接口,哪怕是在開發環境。因此咱們用雲開發的雲函數來 「反代」 接口,下面經過一個例子說一下技術要點。前端
首先在根目錄的 project.config.json
文件裏添加 "cloudfunctionRoot": "functions/"
,而後在根目錄建立文件夾 functions
. 並點擊右鍵建立一個新的雲函數,好比咱們叫 getRegion
。webpack
由於咱們的目標是經過雲函數請求一個未 bei an 的接口,因此爲了更方便的處理異步請求,咱們引入 request-promise
這個庫。git
經過硬盤打開
進入到這個雲函數的文件夾,而後安裝依賴:github
yarn add request request-promise
接下來咱們在 index.js
中寫邏輯,直接上代碼。雲函數經過 event
對象來獲取前端傳過來的參數,而後經過 Promise 對象將結果返回。這個例子中咱們須要拿到region
,web
// 雲函數入口文件 const cloud = require('wx-server-sdk') const rp = require('request-promise') cloud.init() exports.main = async (event, context) => { const region = event.region; const res = await rp({ method: 'get', uri: `https://www.yahoo.com/news/_tdnews/api/resource/WeatherSearch;text=${region}`, json: true }).then((body) => { return { regionList: body } }).catch(err => { return err; }) return res; }
接下來是前端發請求了,注意這裏不能再用 Taro.request()
, 而是雲函數獨有的 wx.cloud.callFunction()
, 由於我如今的 Taro 版本還沒有實現 Taro.cloud.callFunction()
,因此直接用 wx
打頭便可。json
首先封裝一下 wx.cloud.callFunction()
,其實感受什麼卵用🤪:小程序
export const httpClient = (url: string, data: any) => new Promise((resolve, reject): void => { wx.cloud.callFunction({ name: url, data, }).then(res => { resolve(res.result); }).catch(e => { reject(e) }); });
而後咱們在 store 裏面寫邏輯,這樣基本上就解決了數據請求的坑。api
public getRegion = (text: string) => { httpClient('getRegion', { region: encodeURI(text), }) .then((res: any) => { runInAction(() => { if (res.regionList) { this.regionList = res.regionList; } }); }) .catch(() => { setToast(toastTxt.cityFail); }); };
🔔題外話:由於當前版本還沒有實現 Taro.cloud.callFunction()
,因此 lint 會報錯,雖然不影響使用,你們有什麼好的方法,能夠說一下。
在這個項目裏,咱們須要經過小程序拿到的經緯度來反查城市信息,而小程序獲取經緯度須要用戶受權。這裏有個坑,當用戶拒絕受權後,小程序默認詢問受權的 dialog 在一段時間內不會重複彈出,因此咱們必須手動將用戶引導到受權頁面。
之前小程序有個接口叫作 wx.openSetting()
,但 tx 把它廢掉了,如今只能讓用戶點擊一個特定的按鈕。
爲此我作了一個 modal,這裏貼出關鍵代碼。
<Button openType='openSetting' onOpenSetting={() => this.onOpenSetting()}> OK </Button>
首先咱們必須給按鈕聲明 openType='openSetting'
,這樣當用戶點擊了以後就會跳轉到設置頁面。
其次,咱們須要在用戶離開受權頁面時,也就是點擊了左上角那個返回按鈕時,再次去檢查一下用戶的受權狀況。因此咱們要添加onOpenSetting={() => this.onOpenSetting()
,不得不吐槽這個事件命名,明明應該叫作 onLeaveSetting
才合理。
在 onOpenSetting()
方法中咱們再次執行判斷用戶是否受權的方法,未受權的話接着彈 modal,不然放行請求相應的數據接口。
文字有些累,直接看圖。
當用戶關閉搜索
dialog 時,文本框的文字應當被清空,因此一開始寫成下面的這樣,即點擊關閉按鈕時將 inputValue = ''
,然而發現不行。
<Input type='text' value={inputValue} placeholder='Enter City or ZIP code' onInput={e => handleInputTextChange(e)} /> <Button onClick={() => hideSearchDialog()}>Close</Button>
查了一下官方文檔,必須將 Input
和 Button
包裹在一個 Form
下,且要給關閉按鈕加上 formType='reset'
,最後給 Form
添加 onReset
事件指向關閉 dialog 的方法。
<Form onReset={() => hideSearchDialog()}> <Input className={styles.input} type='text' placeholder='Enter City or ZIP code' onInput={e => handleInputTextChange(e)} /> <Button formType='reset'>Close</Button> </Form>;
大可能是編譯問題和它 webpack 配的問題,相應的我都提了 issue,有興趣的話能夠跟進。
舉個例子,<Text>day - night</Text>
,能夠正常編譯,頁面能夠正常看到 day - night
,可是假如是變量,就會被編譯成 day- night
,注意,空格被吃掉了。
const day = 'day' const night = 'night' <Text>{day} - {night}</Text>
我提了個 issue #2261,然並沒人鳥我,有興趣能夠跟進一下。
wx
由於用到了雲開發,而 Taro 現階段尚未Taro.cloud(...)
,因此在使用原生的wx.cloud(...)
時,
ts 確定會報錯。
一開始用的import
來引入靜態文件,但報「找不到路徑」,能夠看下圖(但不影響使用)。提了個 issue #2213,
按照大佬的回覆修改也沒解決問題,實在受不了一片紅,索性改爲了commonJS
.
下面是項目中存在的一些問題,有興趣的話歡迎你們一塊兒討論。
接口圖片的 url 來自aws
,由於衆所周知的緣由,圖片常常會掛掉,
因此有必要在圖片掛掉的時候觸發onError
事件,而後給用戶一個提示。
由於小程序不支持new Image()
,因此只能用官方提供的Image
組件,幸虧這個
組件支持onLoad
和onError
事件。
加載失敗的問題解決了,但由於aws
的速度太慢,因此正常加載時也很不友好(能夠自行體會)
作了一些嘗試,好比先加載縮略圖,再展現完整圖片,但接口提供的最小尺寸的圖片也已經達到了
70 多 k,而且該死的 Yahoo 剛好將圖片 url 控制大小的那段用了加密,因此這個方式 pass 掉了。
如今的作法是在 store 的 構造器加個節流,但不知道這樣合不合理。
construtor() { this.getRegion = _.debounce(this.getRegion, 150); }
老子不再寫小程序了!