Implement scroll wheel control table row width under React ant component, non-hooks


As you can see in the picture, there are too many words in the header.
I originally wanted to implement table dragging to control the width, similar to that of element. Then I searched for plug-ins for a long time and found that most of them were packaged and introduced by myself. There was no one that was easy to use directly. After thinking for a long time, I came up with a curved way to save the country:
That is to use the width of Column to control the row width of the table. Everyone knows that Column can set the width, so we thought of this method. Although this method is a bit complicated, at least it does not require touching the source code. Without further ado, let me briefly describe it. .
Step 1: First, you need to write the width of each Column, as shown in the following code:

<Column width={<!-- -->this.state.tableWidthData[7].w} ellipsis={<!-- -->true} align='center' title="Supplier" dataIndex ="supplier" key="supplier" />

If your Column is a data set, you can still use this method if you don’t write it directly like me, and it’s the same way.

Step 2: Simulate width data to be filled into Column and width. Someone may have noticed this.state.tableWidthData. Let’s first take a look at what this thing is. The following code:

tableWidthData:[
{<!-- -->
w:null,
s:null,
t:0
},
{<!-- -->
w:100,
s:100,
t:0
},
{<!-- -->
w:null,
s:null,
t:0
},

w: This will be used to update the width later, s: the default width, null means free scaling, t: I use it to control the width with clicks, click to expand, and click to restore. You don’t need to use it if you don’t need it. How many headers do you need to write?

Note: If you want to see the packaged version, you can scroll directly to the bottom. This is not a packaged version and is not easy to reuse

Step 3: Write an event. If you want to control the header, you must first get who I clicked and scale the width for whom. Here we use an event of the table:

<Table onHeaderRow={<!-- -->(columns, index)=>{<!-- -->
return {<!-- -->
onClick: (e)=>{<!-- -->this.onHeaderRow(e,columns, index)},
onMouseWheel: (e)=>{<!-- -->this.onMouseWheel(e,columns, index)},
onMouseEnter: (e) => {<!-- -->this.onMouseEnter(e,columns, index)}, // Move the mouse into the row
onMouseLeave: (e) => {<!-- -->this.onMouseLeave(e,columns, index)},
};
}}

Okay, now that you have seen this step, you should probably know how to do it. Without further ado, here’s the code:

onMouseEnter(e,columns, index){<!-- -->
let selectTitle = e.target.innerText
if(!selectTitle){<!-- -->
return
}
let selectedIndex = null
columns.map((v,i)=>{<!-- -->
if(v.title === selectTitle){<!-- -->
selectedIndex = i -1
}
})
this.setState({<!-- -->
selectedIndex:selectedIndex,
saveThis:this
},()=>{<!-- -->
window.onmousewheel = document.onmousewheel = (e)=>{<!-- -->this.onMouseWheel(e,this.state.saveThis)}
})
\t\t\t
};
onMouseLeave(){<!-- -->
window.onmousewheel = document.onmousewheel = null;
};
onMouseWheel(e,saveThis){<!-- -->
let that = saveThis
e = e || window.event;
let tableWidthData = Object.assign([],that.state.tableWidthData)
let w = tableWidthData[that.state.selectedIndex].w?tableWidthData[that.state.selectedIndex].w:0
let th = document.getElementsByClassName('ant-table-thead')[0].childNodes[0].childNodes
let wdith = th[that.state.selectedIndex + 1].offsetWidth
console.log(wdith)
w = w?w:wdith
if(e.wheelDelta){<!-- --> //IE/Opera/Chrome
console.log(e.wheelDelta); // + 150 means up; -150 means down
if(e.wheelDelta > 0){<!-- -->
w++
}else{<!-- -->
if(w > 0){<!-- -->
w--
}
}
} else if (e.detail) {<!-- --> //Firefox pulley event
console.log(e.detail); // + 3 means up; -3 means down
if(e.wheelDelta > 0){<!-- -->
w++
}else{<!-- -->
if(w > 0){<!-- -->
w--
}
}
}
tableWidthData[that.state.selectedIndex].w = w
\t\t  
that.setState({<!-- -->
tableWidthData:tableWidthData
})
console.log(w)
};

onMouseEnter: mouse move event
selectTitle: Get who you are currently touching, and get the title of the table.
selectedIndex: Save the index you are currently clicking on and use it in tableWidthData later.
saveThis: Save this, because this cannot be obtained in the scroll wheel event
onMouseLeave: mouse leaves event
Just cancel the scroll wheel event, there is nothing to say
onMouseWheel: wheel event
tableWidthData: This is the second customized data
w: It is the default width in tableWidthData
th: Get the th of the lower head
wdith: I originally wanted to use w directly, but then I found that it suddenly disappeared. In fact, w was too small. Finally, I obtained th, and then obtained the initial width for w.
If it does not take effect later, you can wait until w is assigned, and then use setState to assign the table data.

Note: This method has a disadvantage, that is, the touch will only be triggered again if it leaves the table header, which is quite uncomfortable. Later, I added a click to get the current subscript. That is the click on the picture.

In fact, dragging can also be done using this method. Since the scroll wheel can be used, other things are definitely also possible, but the requirements are not that many, and it is quite complicated, so I am too lazy to do it.

patch:
The problem with touch mentioned above means that you can only go down and go up to select the next one. Currently, I have found a way to solve it:

componentDidMount(){<!-- -->
let th = document.getElementsByClassName('ant-table-thead')[0].childNodes[0].childNodes
th.forEach((v)=>{<!-- -->
v.onmouseenter = this.onmouseenter.bind(this)
})


onmouseenter(e){<!-- -->
if(!this.state.saveColumns) return
let selectTitle = e.target.innerText
console.log(selectTitle)
if(!selectTitle){<!-- -->
return
}
let selectedIndex = null
this.state.saveColumns.map((v,i)=>{<!-- -->
if(v.title === selectTitle){<!-- -->
selectedIndex = i -1
}
})
this.setState({<!-- -->
selectedIndex:selectedIndex,
})
};

saveColumns: This needs to be assigned in the onMouseEnter event of the code above.

this.setState({<!-- -->
selectedIndex:selectedIndex,
saveThis:this,
saveColumns:columns
},()=>{<!-- -->
window.onmousewheel = document.onmousewheel = (e)=>{<!-- -->this.onMouseWheel(e,this.state.saveThis)}
})

Okay, now there is no problem with the scroll wheel controlling the width and height of the row.

Because the above is a bit complicated and not conducive to reuse, it is encapsulated here to facilitate reuse in other interfaces. The principles are the same. The first and second steps of the above code remain unchanged. The basic data must be first Once done, all the other codes above will be useless

Simplified third step:

<Table onHeaderRow={<!-- -->(columns, index)=>{<!-- -->
return {<!-- -->
onMouseEnter: (e)=>{<!-- -->
React.isWheel(e,columns,Object.assign([],this.state.tableWidthData) ,(d)=>{<!-- -->
console.log(d)
this.setState({<!-- -->
tableWidthData:[...d]
})
})
}, //Mouse the mouse into the row
onMouseLeave: ()=>{<!-- -->window.onmousewheel = document.onmousewheel = null},
};
}}

React.isWheel: This is where I put the encapsulated function isWheel in the React object. You don’t need to write it like this, just put it anywhere and reference it.
tableWidthData: Basic data also needs to be passed in

After simplifying the fourth step, just find a place to put the encapsulated code, then quote it and call it as shown above

function isWheel(e,columns,tableWidthData,callback){<!-- -->
\t
let state = {<!-- -->
selectedIndex:null,
saveColumns:null,
tableWidthData:tableWidthData,
thNodes:[]
}
const onMouseEnter = (e,columns)=>{<!-- -->
let selectTitle = e.target.innerText
console.log(selectTitle)
if(!selectTitle){<!-- -->
return
}
let selectedIndex = null
columns.map((v,i)=>{<!-- -->
if(v.title === selectTitle){<!-- -->
selectedIndex = i -1
}
})
state.selectedIndex = selectedIndex,
state.saveColumns = columns
window.onmousewheel = document.onmousewheel = (e)=>{<!-- -->onMouseWheel(e)}
if(state.thNodes.length === 0){<!-- -->
state.thNodes = document.getElementsByClassName('ant-table-thead')[0].childNodes[0].childNodes
state.thNodes.forEach((v)=>{<!-- -->
v.onmouseenter = (e)=>onmouseenter(e)
})
}
\t\t
\t\t
}
const onmouseenter = (e)=>{<!-- -->
if(!state.saveColumns) return
let selectTitle = e.target.innerText
console.log(selectTitle)
if(!selectTitle){<!-- -->
return
}
let selectedIndex = null
state.saveColumns.map((v,i)=>{<!-- -->
if(v.title === selectTitle){<!-- -->
selectedIndex = i -1
}
})
state.selectedIndex = selectedIndex
}
const onMouseWheel = (e)=>{<!-- -->
e = e || window.event;
let w = state.tableWidthData[state.selectedIndex].w?state.tableWidthData[state.selectedIndex].w:0
let th = document.getElementsByClassName('ant-table-thead')[0].childNodes[0].childNodes
let width = th[state.selectedIndex + 1].offsetWidth
console.log(width)
w = w?w:width
if(e.wheelDelta){<!-- --> //IE/Opera/Chrome
console.log(e.wheelDelta); // + 150 means up; -150 means down
if(e.wheelDelta > 0){<!-- -->
w = w + 3
}else{<!-- -->
if(w > 0){<!-- -->
w = w - 3
}
}
} else if (e.detail) {<!-- --> //Firefox pulley event
console.log(e.detail); // + 3 means up; -3 means down
if(e.wheelDelta > 0){<!-- -->
w = w + 3
}else{<!-- -->
if(w > 0){<!-- -->
w = w - 3
}
}
}
state.tableWidthData[state.selectedIndex].w = w
\t\t
callback(state.tableWidthData)
\t\t
}
\t
\t
onMouseEnter(e,columns)
\t
\t
}

Note: This is an interface with one table. If there are multiple tables in an interface, the 0 in document.getElementsByClassName(‘ant-table-thead’)[0] above needs to be simply changed. Download, just download the dom and upload it.