jQuery WeUI City-Picker Demo:http://www.jqweui.cn/extends#city-picker
官方的city-picker提供了兩種樣式:
(1)省級-市級-區級
(2)省級-市級(不顯示區級)
前端頁面要引入的JS、CSS文件如下
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<!--控制頁面自動適應屏幕大小-->
<meta charset="UTF-8" name="viewport"
content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no">
<title>BORN TO LOVE</title>
<link rel="shortcut icon" href="#">
<!--JQuery-->
<script type="text/javascript" charset="UTF-8" src="resources/scripts/jquery-3.3.1.min.js"></script>
<!--JQuery WEUI-->
<script type="text/javascript" charset="UTF-8" src="resources/scripts/jquery-weui.min.js"></script>
<script type="text/javascript" charset="UTF-8" src="resources/scripts/fastclick.js"></script>
<script type="text/javascript" charset="UTF-8" src="resources/scripts/city-picker.js"></script>
<!--WeUI CSS-->
<link rel="stylesheet" type="text/css" href="resources/css/weui.css">
<link rel="stylesheet" type="text/css" href="resources/css/jquery-weui.css">
</head>
最近開發的應用有一個新的需求,由於是在湖北省內使用,要求不顯示“湖北省”,只選擇市級-區級,而且地址名稱需要自定義。
因此這裏需要解決兩個問題:
#1-> 如何只顯示兩級“市級-區級”?
#2-> 如何實現city-picker數據源動態加載,即數據自定義的問題?
在解決上述問題之前,我們先看看[city-pcker.js]裏的源數據是如何組織的吧 ^^。
[city-pcker.js] 裏的源數據是按JSON格式組織的 rawCitiesData ,例如“湖北省-武漢市-武昌區”的組織結構如下所示。
$.rawCitiesData = [
{
"name":"湖北省",
"code":"420000",
"sub":[
{
"name":"武漢市",
"code":"420100",
"sub":[
{
"name":"武昌區",
"code":"420106"
},
]
},
...
]
}
]
現在來解決第一個問題,如何只顯示“市級-區級”,不顯示“省級”。
思路1:參照官網不顯示區級的做法
直接在 city-picker.js 修改 defaults = $.fn.cityPicker.prototype.defaults 增加 showProvince: true
defaults = $.fn.cityPicker.prototype.defaults = {
showDistrict: true, //是否顯示地區選擇
showProvince: true //是否顯示省份選擇
};
前端頁面初始化添加 showProvice: false
$("#home-city").cityPicker({
title: "選擇目的地",
showProvince: false, //不顯示省級
onChange: function (picker, values, displayValues) {
console.log(values, displayValues);
}
});
但是,並沒有達到想要的效果,沒有任何影響。
原因是這裏相當於只是寫了一個屬性名,必須自定義完善對應的方法,相當於要參照showDistrict的方法寫一套處理showProvince的方法,雖然確實可以實現,但必須要讀懂 city-picker.js 源碼再進行相應的修改,對小白來說太不友好了。
比如下圖展示了源碼中涉及到showDistrict的所有地方,如果要改showProvince只會更麻煩,因爲省份默認是帶sub子節點的,這個結構註定了可以向下追溯,沒法直接從中間節點向上追溯的,感興趣的大神可以自行考慮如何改寫這個邏輯代碼。
思路2:嚴格按照 rawCitiesData 的JSON格式重新組織數據源
原始數據:“湖北省” - “武漢市” - “武昌區”
改寫數據:“武漢市” - “武昌區” - null
{
"name": "武漢市",
"code": "420100",
"sub": [
{
"name": "武昌區",
"code": "420106",
"sub": []
}
]
}
頁面再按照不顯示區級的方法初始化city-picker
$("#home-city").cityPicker({
title: "選擇目的地",
showDistrict: false,
onChange: function (picker, values, displayValues) {
console.log(values, displayValues);
}
});
<body></body>
<h2 class="demos-second-title">只選擇城市</h2>
<div class="weui-cells weui-cells_form">
<div class="weui-cell">
<div class="weui-cell__hd"><label for="home-city" class="weui-label">城市</label></div>
<div class="weui-cell__bd">
<input class="weui-input" id="home-city" type="text" value="武漢市 武昌區">
</div>
</div>
</div>
需要強調的是,這裏的<input>必須初始化value值,不然會報錯
報錯原因分析:
原始的 city-picker.js 裏有一段代碼
//計算value
var val = $(this).val();
if (!val) val = '北京 北京市 東城區';
currentProvince = val.split(" ")[0];
currentCity = val.split(" ")[1];
currentDistrict = val.split(" ")[2];
這段代碼的意思是取input框的value值,如果value爲空則賦值爲“北京 北京市 東城區”,並初始化picker的三層選擇框的省份爲“北京”、城市爲“北京市”、地區爲“東城區”,當點擊這個input框的時候,初始的選擇值就是“北京 北京市 東城區”。但是我們之前已經把 rawCitiesData 進行了重寫,只保留了武漢市的數據,因此如果input不初始化value值,控件找不到這個值,自然會報錯。
解決方式主要有兩種:
一種是直接給input賦值初始value,另一種就是在city-picker.js裏修改上面那段代碼。
需要注意的是value值必須是 rawCitiesData 中初始化的值,不然也會報錯。
//計算value
var val = $(this).val();
if (!val) val = '武漢 武昌區';
currentProvince = val.split(" ")[0];
currentCity = val.split(" ")[1];
currentDistrict = val.split(" ")[2];
演示效果:
現在來解決第二個問題, 如何動態加載數據源,可以自定義數據,滿足個性化需求。
#-> 思路:
要自定義顯示的數據,直接修改 city-picker.js 裏的 rawCitiesData 就行了。
一種方式,自己按照 rawCitiesData 的JSON格式組織自己要的數據,然後粘貼複製替換掉原來的rawCitiesData 就行。這種方式比較適合數據量比較小,且固定後期變動比較小的情況,優點是修改直觀且簡單粗暴。
另一種方式就是實現動態加載數據源,通過外部傳參的方式初始化數據源,數據源可通過ajax的方式去後臺數據庫查詢,然後組織成對應的JSON格式返回前端。這種方式就比較適合數據量比較大且後期數據變動較大的情況,優點是維護方便。
#-> 實現:
首先,我們來看看 city-picker.js 源碼是如何對數據源進行操作的。
其實很簡單,就是設置了一個變量 raw ,然後初始化賦值成數據源 rawCitiesData 。有點類似一個類Class裏直接給屬性賦值初始化的過程,如果要動態修改這個屬性的值,我們通常會增加 set 方法,所以這裏也是一樣的道理,可以給 raw 也增加一個 set 方法,實現動態修改 raw 的值。
// 初始化賦值成空
var raw = [];
// 新增set方式爲raw賦值
var setRawDataList= function (raw_data_list) {
raw = raw_data_list;
}
和構造函數設置參數一樣,這裏 set 方法裏傳入的參數 raw_data_list 也需要修改默認參數設置,新增一個參數 initDataList ,用於接收外部數據源。
defaults = $.fn.cityPicker.prototype.defaults = {
showDistrict: true, //是否顯示地區選擇
initDataList: [] //加載數據源-參數設置
};
最後在 city-picker 初始化的時候爲 raw 進行賦值操作,在 $.fn.cityPicker = function (params) {}裏新增如下代碼,params.initDataList 就是剛剛在defaults裏設置的新增參數。
$.fn.cityPicker = function (params) {
params = $.extend({}, defaults, params);
return this.each(function () {
var self = this;
// 根據外部傳入的參數爲raw賦值
if(params.initDataList != null && params.initDataList.length > 0 ){
setRawDataList(params.initDataList);
}
... // 其他代碼不變
}
主要修改的就只有三個地方,如下圖所示
至此,city-picker.js 修改完畢。
前端<input>html
<h2 class="demos-second-title">請選擇目的地</h2>
<div class="weui-cells weui-cells_form">
<div class="weui-cell">
<div class="weui-cell__hd"><label for="home-city" class="weui-label">城市</label></div>
<div class="weui-cell__bd">
<input class="weui-input" id="home-city" type="text">
</div>
</div>
</div>
city-picker初始化,datalist可以通過ajax去後臺獲取,這裏爲了演示方便直接寫出來了,另外需要注意的是JSON數據要加“[ ]”。
<script>
// 注意要加[] -- datalist可以通過ajax去後臺查詢數據庫獲取
let datalist = JSON.parse("[{\n" +
" \"name\": \"武漢市\",\n" +
" \"code\": \"420100\",\n" +
" \"sub\": [\n" +
" {\n" +
" \"name\": \"市轄區\",\n" +
" \"code\": \"420101\",\n" +
" \"sub\": []\n" +
" },\n" +
" {\n" +
" \"name\": \"江岸區\",\n" +
" \"code\": \"420102\",\n" +
" \"sub\": []\n" +
" },\n" +
" {\n" +
" \"name\": \"江漢區\",\n" +
" \"code\": \"420103\",\n" +
" \"sub\": []\n" +
" },\n" +
" {\n" +
" \"name\": \"礄口區\",\n" +
" \"code\": \"420104\",\n" +
" \"sub\": []\n" +
" },\n" +
" {\n" +
" \"name\": \"漢陽區\",\n" +
" \"code\": \"420105\",\n" +
" \"sub\": []\n" +
" },\n" +
" {\n" +
" \"name\": \"武昌區\",\n" +
" \"code\": \"420106\",\n" +
" \"sub\": []\n" +
" },\n" +
" {\n" +
" \"name\": \"青山區\",\n" +
" \"code\": \"420107\",\n" +
" \"sub\": []\n" +
" },\n" +
" {\n" +
" \"name\": \"洪山區\",\n" +
" \"code\": \"420111\",\n" +
" \"sub\": []\n" +
" },\n" +
" {\n" +
" \"name\": \"東西湖區\",\n" +
" \"code\": \"420112\",\n" +
" \"sub\": []\n" +
" },\n" +
" {\n" +
" \"name\": \"漢南區\",\n" +
" \"code\": \"420113\",\n" +
" \"sub\": []\n" +
" },\n" +
" {\n" +
" \"name\": \"蔡甸區\",\n" +
" \"code\": \"420114\",\n" +
" \"sub\": []\n" +
" },\n" +
" {\n" +
" \"name\": \"江夏區\",\n" +
" \"code\": \"420115\",\n" +
" \"sub\": []\n" +
" },\n" +
" {\n" +
" \"name\": \"黃陂區\",\n" +
" \"code\": \"420116\",\n" +
" \"sub\": []\n" +
" },\n" +
" {\n" +
" \"name\": \"新洲區\",\n" +
" \"code\": \"420117\",\n" +
" \"sub\": []\n" +
" }\n" +
" ]\n" +
" }]");
$("#home-city").cityPicker({
title: "選擇目的地",
// showProvince: false,
showDistrict: false,
initDataList: datalist,
onChange: function (picker, values, displayValues) {
console.log(values, displayValues);
}
});
</script>
參考:https://blog.csdn.net/weixin_41913378/article/details/103175157