La première chose à expliquer est que les tableaux utilisés dans notre projet sont grossièrement divisés en deux catégories. L'une est un tableau ordinaire avec un en-tête non fixe, et l'autre est un en-tête fixe, et la partie tbody
peut défiler. . de. Il convient de noter que l'en-tête fixe nécessite deux table
pour être implémenté, et quiconque l'a fait devrait également comprendre. Le premier semble relativement simple, car la largeur est affectée par le thead
dans th
, tandis que le second semble difficile à gérer, car si vous utilisez deux tables, la situation suivante se produira :
emmm, cela devrait être différent de ce que nous avions imaginé. Comment cela peut-il être résolu ? J'ai l'impression que c'est très difficile à gérer. Je me suis souvenu que j'avais vu le tableau dans element-ui
, et il semble qu'il y ait une implémentation consistant à faire glisser l'en-tête du tableau. Ouvrons la console et jetons un œil à la structure :
Eh bien, c'est tellement long. Je n'ai jamais utilisé les balises
et <colgroup>
, mais si je regarde attentivement, il y a un <col>
au-dessus, et je sais probablement ce qui se passe quand je vois ça. . J'ouvre MDN et regarde la description des attributs associés, et ce que je pense De même, width
peut contrôler la largeur de la colonne actuelle. width
Nous avons résolu le contrôle de la largeur, mais il y a un autre problème, à savoir comment modifier la largeur des autres colonnes après avoir fait glisser, comme suit :
Si je fais glisser la colonne a, comment la largeur modifiée doit-elle être distribuée entre b, c et d ? C'est ainsi que je la gère ici. b, c et d ont des attributs pour indiquer si la colonne a été déplacée. si b, c et d n'ont pas été déplacés, alors la largeur modifiée de a est divisée également en largeur des trois colonnes b, c et d. Si b, c et d sont tous modifiés, alors seule la dernière. la largeur de la colonne d est modifiée. Bon, l'idée est là, on peut la mettre en œuvre.
Il s'avère qu'il serait trop stupide de suivre le design ci-dessus. Il a été modifié pour modifier uniquement les colonnes derrière la colonne déplacée et la largeur de ces colonnes n'a pas changé.
Tout d'abord, la structure html est probablement comme ceci :
<table> <thead> <tr> <th>a<th> <th>b<th> </tr> </thead> <tbody> <tr> <th>1<th> <th>2<th> </tr> </tbody> </table>
aspect js
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: [], }; };
Ajouter dom :
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);
Le bloc ci-dessus est destiné à l'ajout de nœuds et au traitement dom
Pour la réutilisation, ici nous ne nous soucions pas de savoir si l'en-tête est corrigé ou non. Nous le divisons en deux table
et le traitons comme ceci. C'est aussi beaucoup plus pratique.
Déplacez ensuite le doigt vers la droite de la colonne et définissez la valeur de cursor
sur 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; } } };
Il est à noter que le getBoundingClientRect()
obtenu par rigth
est la distance jusqu'au côté droit de l'élément. La distance depuis le bord gauche de la page, et non la distance depuis le bord droit de la page. Voici pour ajouter l'événement thead
à tr
de mousemove
Lorsque le pointeur de la souris est à moins de 8 du bord droit, changez la forme du pointeur, puis changez l'état dans store
, indiquant que le clic. peut être déplacé à ce moment.
Puis mousedown
+mousemove
+mouseup
gère le glisser :
const handleMouseDown = (evt) => if (this.store.draggingColumn) { This.store.dragging = true; Soit {cible } = evt ; Si (!target) revient ; const tableEle = THEADER ; const tableLeft = tableEle.getBoundingClientRect().left; const columnRect = target.getBoundingClientRect(); const minLeft = colonneRect.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 = () => Document.ondragstart = () => Hold.style.display = 'bloc'; Hold.style.left = this.store.startLeft + 'px'; const handleOnMouseMove = (événement) => const deltaLeft = event.clientX - this.store.startMouseLeft ; Const proxyLeft = this.store.startLeft + deltaLeft ; Hold.style.left = Math.max(minLeft, proxyLeft) + 'px' ; } ; //La largeur est allouée comme ceci, par exemple
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!