日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

如何优雅的绘制一棵省市区三级可选择的树?

發布時間:2023/12/2 编程问答 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 如何优雅的绘制一棵省市区三级可选择的树? 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

開始

總結一下 開發過程中的思路想法 各位大佬們看看就好

首先你擁有的數據結構 所有省市區的信息列表 以及已經選中的信息 用的是element-ui的 el-tree

const cityStorage = {provinceList:[{id: 1, provinceId: "110000", name: "北京市"}],//所有省cityList:[{id: 1, cityId: "110100", name: "北京市", provinceId: "110000", zipCode: "102600"}],//所有市districtList:[{id: 1, districtId: "110101", name: "東城區", cityId: "110100"}],//所有區} const selectList = [{ provinceId: "110000",cityId: "110100",districtId: "110101"} ] // 所有選中的省市區 ID 保存的時候也是這個格式

按需渲染

首先 作為有相對要求的開發人員 不會考慮說 直接的去渲染出整個樹 那整個省市區加載的速度絕對會是感人的

那么 可行的解決方法是 一開始 只展示 所有省的信息 點擊展開 時再去渲染下一層 數據

這個對應關系 相對還容易找 每次點擊展開能獲得當前的層級和id 根據層級和id去對應的city和district中過濾就行

這里分享一個小技巧 不通過判斷的方式去對應 而是通過數據的方式

//level , id const levelConfig = {1: {idLabel: 'cityId',fetchLabel: 'cityList',perIdLabel: 'provinceId'},2: {idLabel: 'districtId',fetchLabel: 'districtList',perIdLabel: 'cityId'} }// 那么過濾就可以這么寫 cityStorage[levelConfig[level].fetchLabel].filter(item => item[levelConfig[level].perIdLabel] == id)

獲取數據 然后加載對應下一層 一切到現在為止 都還可以

賦值渲染

再往下 如果我有初始數據呢?

在只展示省信息的情況下 結合前面給的數據格式 怎么展示 這個省是 全選 半選(表示省中有選擇的市或者區但沒選全) 和 不選 ?

第一 你需要設法知道省份滿足全選的條件

第二 你需要設法知道已經選擇的情況

所以這個時候 需要做的 是計數 也就

遍歷一遍 cityStorage.provinceList 和 cityStorage.cityList

往Map中初始化 provinceId cityId 對應的計數

在遍歷 cityStorage.districtList 過程中往Map 對應provinceId cityId 增加計數

那么 有沒有什么別的基礎數據 是要在這個時候初始化的呢?

例如 只給你一個 districtId 你怎么才能最快的 找到他對應的 cityId 和 provinceId

或者 只給你一個 id 怎么最快找到他 對應的 name 呢

我們可以構建一個Map來記錄我們需要的信息

districtId:cityId

cityId:provinceId

那么 我可以通過 Map[districtId] 找到cityId Map[Map[districtId]] 找到 provinceId

id 和 name 的對應關系 也是如此

而這些 可以在 計數的 過程進行

接著 通過已經選擇地區 的 列表 獲取provinceId cityId的數據 的計數

兩份數據都有了

在渲染 省的時候 判斷 兩份Map中對應的計數 是否相同來渲染勾選

那半選的狀態怎么表示呢?el-tree并不支持設置半選的狀態,必須是通過數據的形式呢?

通過模擬子節點的方法 當滿足不全選的情況 模擬兩個子節點

var children = [{id:provinceId '111',label:name,type:'none'},{id:provinceId '222',label:name,type:'none'} ]

然后選中 其中一個 父元素自然就是半選狀態

保存提交

最后是保存提交時候的數據處理

由于模擬了半選狀態 所以最后獲取到的選中的數據 會有兩種

一種常規的6位 還是一種是模擬的d{6}xxx

而且如果 是出現這種d{6}xxx的數據 代表的是它所在的一級有些被選中了 而這些數據還沒有出現在 渲染樹中

這是就 需要有一個數據結構記錄 這種情況

在已選擇的數據 初始化計數的時候 新構建一個Map 存儲 provinceId cityId出現的數據的下標(我這邊保存的是districtId)

provinceId:[districtId,districtId,districtId]

cityId:[districtId,districtId,districtId]

至此 我們最后能拿到的 選中的 id 有 [310000,410000111,510100,610101]

此時這份數據中 有provinceId cityId districtId 以及 模擬的半選數據 怎么盡可能的優雅的生成我們需要的格式呢?

首先是分類 可以發現 xx0000表示的是省 xxx000 xxxx00 表示的是市

let _zeo = item.match(/(0 )$/g),ype = _zeo ? _zeo[0] : '0' switch (type) {case '0':districtList.push(item)break;case '00':case '000':cityList.push(item)break;case '0000':provinceList.push(item)break;}

而這種410000111 數據 可以通過 先前的 Map 將數據并入 districtList 中

接著就是凈化數據

省選擇了 不需要市的所有id 市選擇了 不需要區的所有id

總結 判斷條件

var sub = item.substr(0,2) var re =new RegExp('\^' sub '\\d{4}'); // 省 // var sub = item.substr(0,4) // var re =new RegExp('\^' sub '\\d{2}'); // 市 cityList.filter(code=>!code.match(re))

最后 provinceList cityList districtList 都是有效的選中值

遍歷一遍 cityStorage.districtList 將其中在provinceList cityList中存在id的數據并入 districtList中

此時 districtList 是最終有效的所有選中的 districtId值

此時 cityId = Map[districtId] province=Map[cityId]

寫這個需求的時候 頭真的很大 考慮的再清楚 寫著寫著 還是會有讓人抓狂的問題

展示合并

等等 你以為就這么完了 還有一個展示需求 數據結構還是 保存的那份數據結構

希望展示成

當選擇了一個省份全部地區的時候展示省份名稱

當選擇了一個省份下的部分市時展示市的名稱

當選擇了一個市下的所有地區時,只展示市的名稱

當選擇了一個市下的部分地區時,括號內展示地區名稱

首先還是通過計數 獲取 已經選中的有效的 provinceList cityList districtList

數據格式{provinceId: "110000",cityId: "110100",districtId: "110101"}

構建一個存 selectNameList 用于存放已經選中的 name name可以通過前面的Map[id]獲取

provinceList 選擇的省沒問題 直接推入

cityList 遍歷 構建新的數據 格式 {provinceId: "110000",cityId: "110100",districtId: "1"}

并入 districtList 中

對districtList 根據 cityId 排序

最后 遍歷 districtList 通過標記判斷每次是否是重復的cityId 設置數組 indeterminateNameList 記錄不是全選的市的name

不重復 將標記記為當前cityId 如果上一個元素的 districtCode 是 1 將 indeterminateNameList 存入 selectNameList 中

selectNameList.push('(' indeterminateNameList.join(',') ')')

districtId == 1 全選 存入 selectNameList

districtId != 1 不是全選 存入 indeterminateNameList = [cityId]

在這個過程中 有需要 還可以記錄 cityId 和 indeterminateNameList的管理關系

最終 selectNameList.join(',')

結語

程序猿真的不容易啊 遇到開發時間緊 雜七雜八事情多 還毫無頭緒的時候 壓力真的是大啊


更多專業前端知識,請上 【猿2048】www.mk2048.com

總結

以上是生活随笔為你收集整理的如何优雅的绘制一棵省市区三级可选择的树?的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。