想到作這個,是由於無心中在github上看到了這一個倉庫https://github.com/lunlunshiwo/ChooseCity,作的就是一個城市選擇控件,是用vue寫的,說的是阿里的一道題目,而後想一想本身閒着也是閒着,就動手用react又從新作了一遍。javascript
地址:城市選擇控件css
github: https://github.com/Rynxiao/city-selectorhtml
總體效果以下:vue
我的採用的路由形式,所以沒有作成一個具體的組件(要組件化也就是把state換成props傳值便可),可是在整個頁面中作了很小單元的拆分。另外「上次定位」的功能暫時未完善,容以後補上。java
採用的是react官網提供的腳手架create-react-app,所以總體技術是react
,採用webpack
進行打包構建,jest
測試。同時在此基礎上新增了一些東西。node
腳手架最開始不支持sass,開啓sass須要以下配置:react
# 安裝依賴包 npm install --save node-sass-chokidar npm install --save npm-run-all # 腳本中增長build-css與watch-css # 修改start和build命令,讓其能夠同時運行多個命令 "scripts": { + "build-css": "node-sass-chokidar --include-path ./src --include-path ./node_modules src/ -o src/", + "watch-css": "npm run build-css && node-sass-chokidar --include-path ./src --include-path ./node_modules src/ -o src/ --watch --recursive", "test": "react-scripts test --env=jsdom", - "start": "react-scripts start", - "build": "react-scripts build", + "start-js": "react-scripts start", + "start": "npm-run-all -p watch-css start-js", + "build-js": "react-scripts build", + "build": "npm-run-all build-css build-js" } # .gitignore中去除生成的css文件 src/**/*.css
npm install --save react-router-dom
安裝依賴以後,增長了一個全局入口,在src/container/index.js
中,以下:webpack
<Switch> <Route exact path="/" component={ App } /> <Route path="/city" component={ City } /> </Switch>
增長兩個頁面,路由分別如上配置。ios
須要定位到當前城市,採用的是百度地圖的定位,須要首先去百度地圖開放平臺上申請一個祕鑰,地址在這裏http://lbsyun.baidu.com/apiconsole/key,進去以後查看js文檔,這裏再也不贅述,能夠本身去了解。git
src/public/index.html
中加入百度開放平臺提供的腳本連接,填上本身的祕鑰。<script type="text/javascript" src="http://api.map.baidu.com/api?v=2.0&ak=your_ak"></script>
src/services/locationServices.js
中加入定位代碼async function getLocalCity() { return new Promise(resolve => { var myCity = new window.BMap.LocalCity(); myCity.get(result => { resolve(result.name); }); }); }
獲取城市的接口API,歷經千辛萬苦終於在網上找到了一個能用的【這個接口有可能隨時會掛喲😁😁😁】,可是數據格式可能不太滿意,只能本身轉化。若是不想用這個格式,你也能夠本身起一個後臺服務器,而後輸出你本身喜歡的格式,這裏我算是偷懶了。
以前的格式是按照省份區分的:
格式化以後的格式是按照拼音字母來區分的:
設置代理
由於請求的地址域名不一致,確定會有跨域問題,這裏在package.json中設置了代理,以下:
"proxy": "http://www.msece.com"
獲取城市
// src/services/cityServices.js async function getAllCities() { const json = await axios.get(CITY_API); return formatCites(json); }
UI方面本身沒有什麼創意,因此使用了阿里的antd-mobile
,能夠去這裏看:antd-mobile
// 安裝依賴 npm install antd-mobile --save // 按需加載 // 1. 安裝依賴 npm install react-app-rewired --save-dev npm install babel-plugin-import --save-dev // 2. 在package.json中,將script中的 react-scripts 換成 react-app-rewired // 3. 在根目錄下創建config-overrides.js,內容以下: const { injectBabelPlugin } = require('react-app-rewired'); module.exports = function override(config, env) { config = injectBabelPlugin(['import', { libraryName: 'antd-mobile', style: 'css' }], config); return config; }; // 4. 更改引入方式 // before import Button from 'antd-mobile/lib/button'; // after import { Button } from 'antd-mobile';
進行了組件的拆分,主要爲:
具體能夠參看src/components/city
下的組件
採用的是本地localstorage進行存儲,默認最多存儲兩個,後選擇的城市會替換掉第一個,若是選擇的城市中有相同的,則不進行替換。頁面公用本地存儲,若不想公用,能夠在以後區分id便可。
熱門城市是本身預先定義的,若是不但願預先定義,也能夠參照某些API,這裏算是偷懶。
以前的寫過一篇文章移動端效果之IndexList,具體實現能夠參看。
支持中/英文搜索,中文搜索是進行了全數據遍歷,英文搜索是進行了首字符判斷,而後再進行子集遍歷。在搜索方面,使用了函數節流,若是在1秒中以內尚未輸入完成,則必須進行一次搜索。
// src/utils/index.js function throttle(fn, wait = 500, period = 1000) { let startTime = new Date().getTime(); let timeout; return (...args) => { return new Promise(resolve => { const now = new Date().getTime(); if (now - startTime >= period) { startTime = now; resolve(fn.apply(null, args)); } else { timeout && clearTimeout(timeout); timeout = setTimeout(() => { resolve(fn.apply(null, args)); }, wait); } }); } } // src/pages/city/City.js const searchCity = throttle(searchCityByName); onSearchInput = async value => { if (!value) { this.hideMenuDialog(); return; } const { labels, city } = this.state; const cities = await searchCity(value, labels, city); this.setState({ searchArea: true, searchCities: transformCityMenuData(cities) }); }
原本是想使用heroku
來部署應用的,可是通過一番折騰以後,在heroku的日誌中看到服務是已經啓動了的,可是外網訪問不了,還須要技術支持^_^
後來只能就部署到本身的騰訊雲上面去了,案例地址爲:城市選擇控件
本身看到後就想寫來玩玩而已,在其中也進一步瞭解了測試、react-router 4的用法,以及螞蟻金服的UI庫,也不是說沒有收穫。在項目中,也通過了一系列的代碼重構,好比組件拆分、公共類庫提取等等,寫案例的同時也是在訓練本身的意識,特地分享出來,你們共勉。
最後,代碼倉庫爲:https://github.com/Rynxiao/city-selector,若是以爲有點意思,多謝star。