<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          基于 elementUI table 組件實(shí)現(xiàn)自定義列、寬度、排序并聯(lián)動(dòng)同步

          共 7441字,需瀏覽 15分鐘

           ·

          2021-08-01 18:53

          作者:linong

          來源:SegmentFault 思否社區(qū)


          哈嘍,大家好又是我。昨天有個(gè)人在群里問:“基于 elementUI 如何實(shí)現(xiàn)拖動(dòng)修改列寬度,并同步在多個(gè)表格中”。

          這個(gè)功能其實(shí)聽常見的,在不同的使用者眼中關(guān)注點(diǎn)就應(yīng)該是不一樣的。比如:

          • 項(xiàng)目的主管,更關(guān)心進(jìn)度
          • 前端開發(fā),關(guān)心設(shè)計(jì)稿、接口什么時(shí)候提供
          • 后端開發(fā),關(guān)心前端什么時(shí)候?qū)懲?,什么時(shí)候聯(lián)調(diào)
          • 測試人員,關(guān)心什么時(shí)候提測,以及對應(yīng)人員是誰
          我們的目的是:針對于不同的人群,顯示不同的字段,不同的排序規(guī)則(index、fixed)。那好,我們先來分析一下實(shí)現(xiàn)這樣的功能都需要做什么。

          前期調(diào)研

          elementUI 支持那些功能、回調(diào)?


          1. 寬度控制

            1. 是否提供了回調(diào)函數(shù)?header-dragend(newWidth, oldWidth, column, event) 當(dāng)拖動(dòng)表頭改變了列的寬度的時(shí)候會(huì)觸發(fā)該事件
            2. 是否提供了API用于獲取當(dāng)前寬度配置?沒有提供
            3. 寬度是否可以通過參數(shù)控制?提供,給 el-table-column 組件添加 width 屬性即可。
            4. 參數(shù)是首次有效,還是動(dòng)態(tài)更新?動(dòng)態(tài)更新所以可以使用 :width
            5. 是否提供了拖拽調(diào)整寬度的方案?添加 border ,并且開啟 resizable (默認(rèn)開啟)。
          2. 字段順序
            1. 順序是否可以通過參數(shù)控制?沒提供,看了一遍并且搜索 排序、順序、index 等關(guān)鍵詞并無收獲。主要排序能力都是對內(nèi)容區(qū)域。
            2. 如果無法通過參數(shù)配置,那么通過什么地方可以影響到排序規(guī)則?我們可以通過修改 <el-table-column> 的順序來控制。

          分析

          經(jīng)過調(diào)研 elementUI 發(fā)現(xiàn)可以近乎完成這項(xiàng)工作,那么我們就不考慮其他方案了。只把獲取當(dāng)前寬度配置這一個(gè)問題解決就好了。
          思考??一下,怎么改寬度?這不就 style="width: 10px" 行內(nèi)樣式嘛,這也太簡單了。

          打開控制臺(tái)一看,草率??了,干干凈凈什么都沒有。這就離譜了,??魔法嗎?哈哈,當(dāng)然不是,我們可以看到有個(gè) colgroup、col 標(biāo)簽,專門用來控制列寬。


          那就簡單了,我們直接獲取即可。

          實(shí)現(xiàn)代碼

          寬度控制(自帶)

          重點(diǎn)是加 border
          <el-table :data="tableData" border @header-dragend="headerdragend" style="width: 100%">
              <el-table-column v-for="column in tableTitleList" :fixed="column.fixed" :prop="column.prop"
                  v-if="column.isShow"
                  :label="column.label" :width="column.width">
              </el-table-column>
              <el-table-column fixed="right" label="操作" width="100">
                  <template slot-scope="scope">
                      <el-button @click="handleClick(scope.row)" type="text" size="small">查看</el-button>
                      <el-button type="text" size="small">編輯</el-button>
                  </template>
              </el-table-column>
          </el-table>

          操作之后獲取寬度 @header-dragend

          通過 @header-dragend 拿到通知,然后去獲取節(jié)點(diǎn)上的真實(shí)數(shù)據(jù)
          headerdragend(newWidth, oldWidth, column, e) {
              // 獲取到觸發(fā)節(jié)點(diǎn),也就是你拖動(dòng)的是哪一個(gè)
              var el = e.target;
              
              // 獲取到當(dāng)前 table 的 colgroup col 節(jié)點(diǎn),用于后面獲取寬度
              // getParentNodes 是一個(gè)模仿 $(el).parents() 的方法
              var colList = getParentNodes(el, 'table').querySelectorAll('colgroup col');
              
              // 獲取當(dāng)前拖動(dòng)的是第幾個(gè),方便后續(xù)檢測 DOM 是否已更新
              var currentColIndex = this.tableTitleList.findIndex(item=>item.label == column.label);
              if(currentColIndex == -1){
                  return console.warn('找不到拖動(dòng)列')
              }
              
              // 修改配置列表,把當(dāng)前列設(shè)置為固定寬度
              this.tableTitleList[currentColIndex].widthEnable = true;

              // 起了一個(gè)定時(shí)任務(wù)去獲取最終的寬度
              clearInterval(headerDragendInterval)
              headerDragendInterval = setInterval(()=>{
                  // 判斷一下目標(biāo)列的寬度是否為最終寬度
                  if(colList[currentColIndex].width == newWidth){
                      this.changeColumnWidth(colList);
                      clearInterval(headerDragendInterval)
                  }else if(colList[currentColIndex].width == oldWidth){
                      console.info('需要等待渲染')
                  }else{
                      console.warn('異常值');
                      this.changeColumnWidth(colList);
                      clearInterval(headerDragendInterval)
                  }
              }, 10)
          }

          控制順序

          因?yàn)閿?shù)組是有順序的嘛,所以使用 v-for 來循環(huán),然后改變數(shù)組中的順序,就可以改變渲染出來的內(nèi)容順序
          <el-table :data="tableData" border @header-dragend="headerdragend" style="width: 100%">
              <el-table-column v-for="column in tableTitleList" :fixed="column.fixed" :prop="column.prop"
                  v-if="column.isShow"
                  :label="column.label" :width="column.width">
              </el-table-column>
              <el-table-column fixed="right" label="操作" width="100">
                  <template slot-scope="scope">
                      <el-button @click="handleClick(scope.row)" type="text" size="small">查看</el-button>
                      <el-button type="text" size="small">編輯</el-button>
                  </template>
              </el-table-column>
          </el-table>

          拖動(dòng)排序

          這塊我直接使用 Sortable 來實(shí)現(xiàn)功能,正好也是群里一個(gè)人問的。在 onEnd 的時(shí)候把操作同步到數(shù)據(jù)源就OK了
          initSort(){
              var el =  document.querySelector('#sortWrap')
              var that = this;
              Sortable.create(el, {
                  delay: 100,
                  sort: !0,
                  forceFallback: !0,
                  scrollSensitivity: 100,
                  animation: 150,
                  ghostClass: "gift-ghost-item",
                  chosenClass: "gift-chosen-item",
                  onEnd: function(t) {
                      that.tableTitleList.splice(
                          t.newIndex, 
                          0, 
                          that.tableTitleList.splice(t.oldIndex, 1)[0]
                      )
                  }
              })

          },
          測試地址:
          http://www.lilnong.top/static/html/vue-elementUI-table-resize-thead.html


          點(diǎn)擊左下角閱讀原文,到 SegmentFault 思否社區(qū) 和文章作者展開更多互動(dòng)和交流,掃描下方”二維碼“或在“公眾號后臺(tái)回復(fù)“ 入群 ”即可加入我們的技術(shù)交流群,收獲更多的技術(shù)文章~

          - END -


          瀏覽 105
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  亚洲AV高清在线 | 国产操逼AV电影 | 成人A片区| 日韩三级网址 | 在线中文字幕区 |