想到作这个,是由于无心中在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。