Heim > Artikel > Web-Frontend > So implementieren Sie einen ziehbaren Tabellenkopf
Das erste, was zu erklären ist, ist, dass die in unserem Projekt verwendeten Tabellen grob in zwei Kategorien unterteilt sind: Eine ist eine normale Tabelle mit einem nicht fixierten Header und die andere ist ein fester Header, und der Teil tbody
kann gescrollt werden . von. Es ist zu beachten, dass für die Implementierung des festen Headers zwei table
erforderlich sind, und jeder, der dies getan hat, sollte dies auch verstehen. Ersteres scheint relativ einfach zu sein, da die Breite durch thead
in th
beeinflusst wird, während letzteres schwierig zu handhaben zu sein scheint, da bei Verwendung von zwei Tabellen die folgende Situation auftritt:
emmm, das sollte anders sein, als wir es uns vorgestellt haben. Wie kann man das beheben? Mir fiel ein, dass ich die Tabelle in element-ui
gesehen hatte, und es scheint, dass es eine Implementierung zum Ziehen des Tabellenkopfes gibt. Öffnen wir die Konsole und schauen uns die Struktur an:
Nun, es ist so lang, dass ich die Tags <colgroup>
und <col>
noch nie verwendet habe, aber wenn ich genau hinschaue, ist da ein width
, und ich weiß wahrscheinlich, was los ist Schauen Sie sich die Beschreibung der zugehörigen Attribute an und was ich denke. Ebenso kann width
die Breite der aktuellen Spalte steuern.
Wir haben die Breitensteuerung gelöst, aber es gibt noch ein anderes Problem, nämlich wie man die Breite anderer Spalten nach dem Ziehen wie folgt ändern kann:
a | b | c | d |
---|
Wenn ich Spalte a ziehe, wie soll die geänderte Breite auf b, c und d verteilt werden? So gehe ich hier mit den Attributen b, c und d um, die angeben, ob die Spalte gezogen wurde. Wenn b, c und d nicht verschoben wurden, wird die geänderte Breite von a gleichmäßig auf die Breite der drei Spalten b, c und d aufgeteilt. Wenn b, c und d alle geändert werden, dann nur die letzte Spalte d wird geändert. Okay, die Idee ist da, wir können sie umsetzen.
Es stellt sich heraus, dass es zu dumm wäre, dem obigen Design zu folgen. Es wurde geändert, um nur die Spalten hinter der gezogenen Spalte zu ändern, und die Breite dieser Spalten hat sich nicht geändert.
Zuallererst sieht die HTML-Struktur wahrscheinlich so aus:
<table> <thead> <tr> <th>a<th> <th>b<th> </tr> </thead> <tbody> <tr> <th>1<th> <th>2<th> </tr> </tbody> </table>
js-Aspekt
constructor (id, options) { this._el = document.querySelector(`#${id}`); // 实际使用中需要对dom结构进行判断,这里就不做了 this._tables = Array.from(this._el.querySelectorAll('table')); setTimeout(() => this._resolveDom()); this.store = { dragging: false, //是否拖动 draggingColumn: null, //拖动的对象 miniWidth: 30, //拖动的最小宽度 startMouseLeft: undefined, //鼠标点击时的clientX startLeft: undefined, //th右离table的距离 startColumnLeft: undefined, //th左离table的距离 tableLeft: undefined, //table离页面左边的距离, HColumns: [], BColumns: [], }; };
Dom hinzufügen:
const [ THeader ] = this._tables; let TBody; const Tr = THeader.tHead.rows[0]; const columns = Array.from(Tr.cells); const Bcolgroup = document.createElement('colgroup'); const cols = columns.map((item, index) => { const col = document.createElement('col'); item.dataset.index = index; col.width = +item.offsetWidth; return col; }); cols.reduce((newDom, item) => { newDom.appendChild(item); return newDom; }, Bcolgroup); const HColgroup = Bcolgroup.cloneNode(true); THeader.appendChild(HColgroup); //不管是一个table还是两个,都把header和body提出来 if (this._tables.length === 1) { const [ , tbody ] = Array.from(THeader.children); tbody.remove(); TBody = THeader.cloneNode(); TBody.appendChild(Bcolgroup); TBody.appendChild(tbody); this._el.appendChild(TBody); } else { [ , TBody ] = this._tables; TBody.appendChild(Bcolgroup); } //拖动时的占位线 const hold = document.createElement('p'); hold.classList.add('resizable-hold'); this._el.appendChild(hold);
Der obige Block dient dem Hinzufügen von Knoten und der Verarbeitung dom
Für die Wiederverwendung ist es uns egal, ob der Header fest ist oder nicht. Wir teilen ihn in zwei Teile auf table
und verarbeiten ihn so Es ist auch viel bequemer.
Bewegen Sie dann den Finger auf die rechte Seite der Spalte und setzen Sie den Wert von cursor
auf col-resize
:
handleMouseMove(evt) { //... if (!this.store.dragging) { const rect = target.getBoundingClientRect(); const bodyStyle = document.body.style; if (rect.width > 12 && rect.right - event.pageX < 8) { bodyStyle.cursor = 'col-resize'; target.style.cursor = 'col-resize'; this.store.draggingColumn = target; } else { bodyStyle.cursor = ''; target.style.cursor = 'pointer'; this.store.draggingColumn = null; } } };
Es ist zu beachten, dass getBoundingClientRect()
durch rigth
erhalten wird ist der Abstand zur rechten Seite des Elements. Der Abstand vom linken Rand der Seite, nicht der Abstand vom rechten Rand der Seite. Hier ist das thead
-Ereignis, das zu tr
s mousemove
hinzugefügt wurde. Wenn der Mauszeiger weniger als 8 vom rechten Rand entfernt ist, ändert sich die Zeigerform und dann wird der Status in store
geändert, was darauf hinweist Der Klick kann zu diesem Zeitpunkt gezogen werden.
Dann übernimmt mousedown
+mousemove
+mouseup
das Ziehen:
const handleMouseDown = (evt) => if (this.store.draggingColumn) { This.store.dragging = true; Sei {target} = evt; If (!target) return; const tableEle = THeader; const tableLeft = tableEle.getBoundingClientRect().left; const ColumnRect = target.getBoundingClientRect(); const minLeft = columnsRect.left - tableLeft + 30; Target.classList.add('noclick'); This.store.startMouseLeft = evt.clientX; This.store.startLeft = ColumnRect.right - tableLeft; This.store.startColumnLeft = ColumnRect.left - tableLeft; This.store.tableLeft = tableLeft; Document.onselectstart = () => false; Document.ondragstart = () => false; Hold.style.display = 'block'; Hold.style.left = this.store.startLeft + 'px'; const handleOnMouseMove = (event) => Const deltaLeft = event.clientX - this.store.startMouseLeft; Const ProxyLeft = this.store.startLeft + deltaLeft; Hold.style.left = Math.max(minLeft, ProxyLeft) + 'px'; }; //Die Breite wird beispielsweise so zugewiesen
Das obige ist der detaillierte Inhalt vonSo implementieren Sie einen ziehbaren Tabellenkopf. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!