iT邦幫忙

0

vue 三層式下拉選單請益

  • 分享至 

  • xImage

以前沒寫過三層式下拉選單,目前是按照先前寫雙層式下拉選單的邏輯模仿而來的,
處理的方式是一次撈取整包資料再用computed處理成連動的選單,因此當資料越來越大包時一開始的載入就會很久;因為以前最多就雙層而以不至於會太大包。

想問是否有甚麼方法可以改善呢?還是我應該每一層選項change的時候才去從後端撈出下一個子層的資料呢,但不曉得這樣是不是好的寫法還沒試過。

此URL為三層下拉選單的程式 https://jsfiddle.net/5b2uLfp9/

以下為選單的資料表大概的樣子為folder->scan->host

 const folderdata1 = [
            { folderid: 27, foldername: 'A', scanid: 28, scanName: 'apple' ,hostid:1,hostname:'applepie'},
            { folderid: 4588, foldername: 'B', scanid: 4732, scanName: 'Black', hostid:2,hostname:'BlackCoffee'},
            { folderid: 4588, foldername: 'B', scanid: 4732, scanName: 'Black', hostid:8,hostname:'BlackMan'},
            { folderid: 4588, foldername: 'B', scanid: 4665, scanName: 'Blue' , hostid:3,hostname:'BlueBird'},
          	{ folderid: 4588, foldername: 'B', scanid: 4665, scanName: 'Blue' , hostid:4,hostname:'BlueSky'},
            { folderid: 4588, foldername: 'B', scanid: 4665, scanName: 'Blue' , hostid:5,hostname:'BlueTears'},
        ]

以下為主要computed的程式碼

data() {
    return {           
             input: {
                  folder: null,
                  scan: null,
                  host:null,
                    },
             folders: [],
           }
         },
created() {
    this.folders = folderdata1 //之後要接的選單資料
         },
computed: {
     parentList() {
              let obj = {
                  sort: [],
                  map: {}
                      }
            this.folders.forEach(({ folderid, foldername, scanid, scanName,hostid,hostname }, index) => {
                        if (!obj.map[foldername]) {
                            obj.sort.push(foldername)
                            // mapObj建立一個foldername 的屬性,值是 sort,map
                            obj.map[foldername] = {
                                sort: [],
                                map: {},
                            }
                        }
                        if(!obj.map[foldername].map[scanName]){
                        	obj.map[foldername].sort.push(scanName)
                        	obj.map[foldername].map[scanName] = { index, scanid,sort:[],map:{} }
                        }
                        obj.map[foldername].map[scanName].sort.push(hostname)
                        obj.map[foldername].map[scanName].map[hostname]={index,hostid,hostname}
                    })
                    return obj;
                },
       childrenList() {
               this.input.scan = null
               if (this.input.folder) {
                     return  this.parentList.map[this.input.folder]
               } else {
                     return []
                     }
                },
        grandsonList() {
                this.input.host = null
                if (this.input.scan) {
                     return this.childrenList.map[this.input.scan]
                } else {
                     return []
                    }
                },
          },
canrong iT邦新手 3 級 ‧ 2022-06-02 10:37:24 檢舉
ajax 一層驅動一層
在folder跟scan都在新增@change事件 驅動是嗎?
canrong iT邦新手 3 級 ‧ 2022-06-02 14:07:37 檢舉
一個少量多餐的概念,當需要時再去取,一次取需要的量就好。的確以一套流程來說,所有資料一次取得是比一直去讀取好,這是減少I/O次數優化效能的方法,但考慮到使用者體驗,使用者並非會選擇到該選項時,你可以考慮只讀取第一層或者第一層選項與初始選項的下兩層,其他的選項當然是等選到後再去更新它。
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 個回答

0
froce
iT邦大師 1 級 ‧ 2022-06-02 11:05:04
  1. 你的這結構也太奇怪了吧...一般來說會表示成樹狀
 const folderdata1  = [
            { folderid: 27, foldername: 'A', children:[{scanid: 28, scanName: 'apple', children: [{hostid:1,hostname:'applepie'}]}]},
            {folderid: 4588, foldername: 'B', children: [{scanid: 4732, scanName: 'Black', children: [{hostid:2,hostname:'BlackCoffee'}, {hostid:8,hostname:'BlackMan'}]}, {scanid: 4665, scanName: 'Blue', children: [{hostid:3,hostname:'BlueBird'}, {hostid:4,hostname:'BlueSky'}, {hostid:5,hostname:'BlueTears'}]}]}
        ]
  1. 樹狀的話你可以分層解析,甚至做遞迴去自動生成組件。

  2. 比較常用的還是ajax去一層一層取就是了。

2.因為想說接資料也是一整包接回來,就沒特地改成樹狀了。
3.您是說我應該改成FOLDER:@change觸發 ajax抓scan->Scan:@change觸發 ajax 抓host 比較好?

我是以前剛學連動下拉選單的時候,爬文看估狗上大家分享的都是一整包資料再去做連動選單的。想說是不是直接一包取回來再處理就好,但最近想到這樣第三層資料變多的話會載入蠻久的

froce iT邦大師 1 級 ‧ 2022-06-02 14:57:24 檢舉

一次整包接回來通常是為了教學,畢竟要寫ajax還得說明後端比較麻煩。

froce iT邦大師 1 級 ‧ 2022-06-02 16:03:27 檢舉

要快的話你還是得惰性取值,不是一次做map。
https://codepen.io/froce-lu/pen/oNEdVrq

重點:

  1. 利用Set資料結構,將stringfy後的資料儲存,確保選項不重複
  2. 在select:onchange的時候,重設後面階層的選項,並且重新產生下一階層的選項

要更快的話或許可以搞個cache記住各階層的選項。

我要發表回答

立即登入回答