5
头图

Hello, everyone, it's me again. Yesterday someone asked in the group: "How to drag based on elementUI to modify column width , and synchronize in multiple tables " .

This function actually sounds common. Different users of eyes of 161035b84bccf7. for example:

  • The project manager is more concerned about the progress
  • Front-end development, care about when the design draft and interface will be provided
  • Back-end development, care about when the front-end is finished and when is the joint debugging
  • Testers, care about when to test, and who the corresponding personnel are

Our purpose is: for different groups of people, display different fields, different sorting rules (index, fixed) . Well, let's first analyze what needs to be done to achieve such a function.

Preliminary investigation

What functions and callbacks does elementUI support?

  1. Width control

    1. Can the width be controlled by parameters? Provided, add the width attribute el-table-column
    2. Is the parameter valid for the first time or is it dynamically updated? Dynamic update so you can use :width
    3. Is there a solution for dragging and adjusting the width? Add border and enable resizable (enabled by default).

      1. Is a callback function provided? header-dragend(newWidth, oldWidth, column, event) This event is triggered when the width of the column is changed by dragging the header
      2. Is there an API to get the current width configuration? not provided
  2. Field order

    1. Can the sequence be controlled by parameters? did not provide . I read it and searched for sort, order, index and other keywords to no avail. The main sorting capabilities are all on the content area.
    2. If it cannot be configured through parameters, where can the sorting rules be affected? We can control it by modifying the sequence of <el-table-column>

analyze

After investigating elementUI, it is found that this work can be almost completed, so we do not consider other options. Just solve the problem of obtaining the current width configuration

Think 🤔, how to change the width? This is not the style="width: 10px" inline style, it is too simple.

image.png

When I opened the console, I was sloppy, and there was nothing clean. This is outrageous, 🪄Magic? Haha, of course not. We can see that there are colgroup and col tags, specifically used to control the column width.

image.png

That's simple, we can get it directly.

Implementation code

Width control (included)

The point is to add 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>

Get the width after the operation @header-dragend

Get the notification through @header-dragend , and then get the real data on the node

headerdragend(newWidth, oldWidth, column, e) {
    // 获取到触发节点,也就是你拖动的是哪一个
    var el = e.target;
    
    // 获取到当前 table 的 colgroup col 节点,用于后面获取宽度
    // getParentNodes 是一个模仿 $(el).parents() 的方法
    var colList = getParentNodes(el, 'table').querySelectorAll('colgroup col');
    
    // 获取当前拖动的是第几个,方便后续检测 DOM 是否已更新
    var currentColIndex = this.tableTitleList.findIndex(item=>item.label == column.label);
    if(currentColIndex == -1){
        return console.warn('找不到拖动列')
    }
    
    // 修改配置列表,把当前列设置为固定宽度
    this.tableTitleList[currentColIndex].widthEnable = true;

    // 起了一个定时任务去获取最终的宽度
    clearInterval(headerDragendInterval)
    headerDragendInterval = setInterval(()=>{
        // 判断一下目标列的宽度是否为最终宽度
        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)
}

Control sequence

Because the array is in order, use v-for to loop, and then change the order in the array, you can change the order of the rendered content

<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>

Drag sort

I used Sortable directly to implement the function, which happened to be asked by a person in the group. It is OK to synchronize the operation to the data source at onEnd

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]
            )
        }
    })

},

I was in a hurry to leave work and forgot the test address


linong
29.2k 声望9.5k 粉丝

Read-Search-Ask