常常會在一些項目中用到地址選擇的東西,特別是在一些在線商城要填寫收貨地址的時候,省市區3個聯動的下拉列表是最經常使用的。而後我也忽然有一天在一個小項目中要有收貨地址時,忽然發現好像沒有一個現成的庫(要能直接npm install xxx
)去使用😰,而後在github去搜了一圈,確實發現有json格式的原始數據,可是結構是同一級的,很難區分是省仍是市或者區,雖然做者提供了jquery的插件,可是畢竟是在手機端使用,最好仍是能直接經過js去操做(這樣在nodejs服務端也能使用)。因此決定把原始數據進行從新格式化,轉成省市區嵌套的格式,這樣的話就很容易經過省的ID去拿到市的列表,而後經過市的ID又能拿到區的列表,這正是咱們的聯動下拉列表想要的結構。javascript
最終要想的結構以下:html
{
"320000": {
"code": "320000",
"name": "江蘇省",
"cities": {
"320100": {
"code": "320100",
"name": "南京市",
"districts": {
"320102": "玄武區",
"320104": "秦淮區",
//...
}
}
//...
}
}
//...
}
複製代碼
咱們經過code的前2位來肯定省,中間2位來肯定市,最後2位來肯定區,因此若是是前兩位同樣的就說明是屬於同一個省的,中間2個同樣的就說明是同一個市的,以此類推,須要注意的是上海北京這樣的直轄市,省跟市都是上海,市的code爲00,並且只有一個市,下面的區的中間2位code均爲01,這裏在轉數據的時候須要注意。java
基於上面的邏輯,寫了個簡單的轉換的js,並提供簡單的API來直接給外面調用🍺。 首先安裝庫china-location:node
npm install china-location --save
複製代碼
或者react
yarn add china-location
複製代碼
而後在JS裏面jquery
//跟庫一塊兒綁定轉換好的數據
import list from 'china-location/dist/location.json'
//in node.js
//const list = require('china-location/dist/location.json');
//ES6 import
import ChinaLocation from 'china-location';
//提供獲取地址,修改地址API的類
//in node.js
//const ChinaLocation = require('china-location');
//初始化實例,並傳入json數據
const location = new ChinaLocation(list);
//獲取初始時當前地址包括code及中文名
//{
// province: {code: '110000', name: '北京市'},
// city: {code: '110000', name: '北京市'},
// district: {code: '110101', name: '東城區'}
//}
const defaultLocation = location.getCurrentAddress();
//修改地址
const newProvince = '320000';
const newCity = '320500';
const newDistrict = '320509';
//通常使用聯動下拉框,獲取選中的code來更新地址,得到下一級的數據
location.changeProvince(newProvince);
location.changeCity(newCity);
location.changeDistrict(newDistrict);
//也能夠一次性都修改
location.changeLocation(newProvince, newCity, newDistrict);
//{
// province: {code: '320000', name: '江蘇省'},
// city: {code: '320500', name: '蘇州市'},
// district: {code: '320509', name: '吳江區'}
//}
//獲取更新後的地址信息
const newLocation = location.getCurrentAddress();
複製代碼
API很簡單,初始化,而後修改當前地址,最後獲取當前地址。有了這樣的庫,咱們就能夠很方便的在瀏覽器頁面,或者在node.js端很容易的去作跟地址相關的邏輯🎉。git
china-location
打包進的數據可能不是最新的,可是原始數據可能已經更新過,爲了能不重複發佈版本,也能使用最新的數據,china-location
也提供了簡單的npm script來轉換本地自定義的原始數據,而後再new ChinaLocation(latestData)
初始化的時候傳入本身手動轉換的json數據。 首先clone原始數據repo:mumuy/data_location, 或者直接把裏面的list.json
保存下來,而後git clone china-location:github
git clone git@github.com:JasonBoy/china-location.git
cd china-location
複製代碼
進入chian-location根目錄後使用reformat
script來轉換:npm
npm run reformat -- /path/to/data_location/list.json
複製代碼
--
後面跟的參數就是原始數據的本地路徑,成功之後會輸出到dist
目錄,裏面的location.json
和location.min.json
, 而後直接拷到你的項目中import,傳到new ChinaLocation(data)
構造函數便可使用最新的數據了。json
以上是純JS的使用,固然若是咱們的開發用一些UI庫的話,好比React, 我也寫了個簡單的React組件react-china-location, 樣式都是html原生的下拉框樣式,這裏只作一個demo使用,你能夠根據這個邏輯作出符合項目UI要求的組件:
在react-china-location
裏面的china-location
是放在peerDependences
中的,因此china-location
也須要單獨安裝:
npm install china-location react-china-location --save
複製代碼
而後在你的JSX中:
import locationData from 'china-location/dist/location.json';
import ChinaLocation from 'react-china-location';
class App extends React.Component {
constructor (props) {
super(props);
this.onLocationChange = this.onLocationChange.bind(this);
this.state = {
currentLocation: {},
}
}
onLocationChange (newLocation) {
//{
// province: {code: '110000', name: '北京市'},
// city: {code: '110000', name: '北京市'},
// district: {code: '110101', name: '東城區'}
//}
console.log(newLocation);
//更新到state
this.setState({
currentLocation: newLocation,
});
}
render () {
<div>
<ChinaLocation list={locationData} onLocationChange={this.onLocationChange}/> </div>
}
}
複製代碼
<ChinaLocation>
組件裏的list
prop就是轉換後的json數據, 而onLocationChange
回調是當用戶選擇不一樣的省市區時的回調,會傳入最新的location數據,而後就能夠setState更新到頁面的其餘UI上。
但願這個簡單的china-location庫能給其餘的小夥伴在項目中使用到地址邏輯的時候帶來方便,作到開箱即用,而無需浪費時間本身手動再寫一遍, 把更多的時間專一在本身業務邏輯上。