BS 아키텍처를 사용하는 엔터프라이즈 수준 애플리케이션에서 테이블에 많은 수의 열이 있는 경우 일반적인 사용자 요구 사항은 처음 몇 개의 중요한 열을 수정하는 것입니다. 이러한 방식으로 고정된 열을 사용하면 사용자가 드래그할 때 데이터를 쉽게 볼 수 있습니다. 스크롤 막대. 사용자 경험이 훌륭합니다. 일부 헤비급 JS 구성 요소 라이브러리에도 이 기능이 있는데, 이 기능을 달성하는 더 쉬운 방법이 있습니까?
이 요구 사항에 대한 일반적인 솔루션은 테이블 접합을 사용하는 것입니다. 간단한 기능으로 정적 웹 페이지나 동적 페이지를 만들려는 경우 논리가 비교적 간단하고 기술이 복잡하지 않습니다. 하지만 동적 함수가 많으면 중복되는 코드를 많이 작성해야 하고, 이는 유지 관리가 어렵습니다. 간단한 함수라도 이벤트 처리 등 많은 코드를 작성해야 합니다. 유연성이 부족하고 좋은 솔루션이 아닙니다.
오랜 기간의 분석과 연구, 다양한 시나리오 실험 끝에 호환성이 매우 좋은 솔루션을 찾았습니다. 일반적으로 위치 계산 방법을 사용하므로 아래에 코드를 게시하고 설명하겠습니다.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>无标题文档</title> <script type="text/javascript"> function divScroll(scrollDiv){ var scrollLeft = scrollDiv.scrollLeft; document.getElementById("tableDiv_title").scrollLeft = scrollLeft; document.getElementById("tableDiv_body").scrollLeft = scrollLeft; } function divYScroll(scrollYDiv){ var scrollTop = scrollYDiv.scrollTop; document.getElementById("tableDiv_y").scrollTop = scrollTop; } function onwheel(event){ var evt = event||window.event; var bodyDivY = document.getElementById("tableDiv_y"); var scrollDivY = document.getElementById("scrollDiv_y"); if (bodyDivY.scrollHeight>bodyDivY.offsetHeight){ if (evt.deltaY){ bodyDivY.scrollTop = bodyDivY.scrollTop + evt.deltaY*7; scrollDivY.scrollTop = scrollDivY.scrollTop + evt.deltaY*7; }else{ bodyDivY.scrollTop = bodyDivY.scrollTop - evt.wheelDelta/5; scrollDivY.scrollTop = scrollDivY.scrollTop - evt.wheelDelta/5; } } } </script> <style type="text/css"> body { margin:0; padding:0; } table { border-collapse:collapse; border:0; border:none; } table td { border:1px solid #000; overflow:hidden; padding:0 2px; } </style> </head> <body> <div style="width:500px; position:relative; padding-right:18px;"> <div style="position:relative;height:368px;overflow:hidden;width:100%"> <div style="padding-left:108px; width:auto; overflow:hidden; background:#f00;" id="tableDiv_title" > <table border="0" cellspacing="0" cellpadding="0" > <tr> <td style="min-width:30px; max-width:30px; left:0; top:0; width:30px; overflow:hidden; background-color:#f00;position:absolute;z-index:1;">000</td> <td style="min-width:74px; max-width:74px; left:30px; top:0; width:74px; overflow:hidden; background-color:#f00;position:absolute;z-index:1;">自动表格</td> <td style="min-width: 100px; max-width: 100px; width: 100px;" >56454自动</td> <td style="min-width: 100px; max-width: 100px; width: 100px;" >56454自动</td> <td style="min-width: 100px; max-width: 100px; width: 100px;" >56454自动</td> <td style="min-width: 100px; max-width: 100px; width: 100px;" >56454自动</td> <td style="min-width: 100px; max-width: 100px; width: 100px;" >56454自动</td> <td style="min-width: 100px; max-width: 100px; width: 100px;" >最后一列</td> </tr> </table> </div> <div style="overflow:hidden; position:absolute;height:128px; width:100%;" id="tableDiv_y" onmousewheel="onwheel(event);" onwheel="onwheel(event);"> <div style="padding-left:108px; width:auto;overflow:hidden;" id="tableDiv_body"> <table border="0" cellspacing="0" cellpadding="0" > <tr> <td style="min-width:30px; max-width:30px; left:0; width:30px; overflow:hidden; background-color:#fff;position:absolute;z-index:1;">001</td> <td style="min-width:74px; max-width:74px; left: 30px; width: 74px; overflow:hidden; background-color:#fff;position:absolute;z-index:1;">自动表格</td> <td style="min-width: 100px; max-width: 100px; width: 100px;" >56454自动</td> <td style="min-width: 100px; max-width: 100px; width: 100px;" >56454自动</td> <td style="min-width: 100px; max-width: 100px; width: 100px;" >56454自动</td> <td style="min-width: 100px; max-width: 100px; width: 100px;" >56454自动</td> <td style="min-width: 100px; max-width: 100px; width: 100px;" >56454自动</td> <td style="min-width: 100px; max-width: 100px; width: 100px;" >最后一列</td> </tr> <tr> <td style="min-width:30px; max-width:30px; left:0; width:30px; overflow:hidden; background-color:#fff; position:absolute; z-index:1;">002</td> <td style="min-width:74px; max-width:74px; left:30px; width:74px; overflow:hidden;background-color:#fff; position:absolute; z-index:1;">自动表格</td> <td style="min-width: 100px; max-width: 100px; width: 100px;" >56454自动</td> <td style="min-width: 100px; max-width: 100px; width: 100px;" >56454自动</td> <td style="min-width: 100px; max-width: 100px; width: 100px;" >56454自动</td> <td style="min-width: 100px; max-width: 100px; width: 100px;" >56454自动</td> <td style="min-width: 100px; max-width: 100px; width: 100px;" >56454自动</td> <td style="min-width: 100px; max-width: 100px; width: 100px;" >最后一列</td> </tr> <tr> <td style="min-width:30px; max-width:30px; left:0; width:30px; overflow:hidden; background-color:#fff;position:absolute;z-index:1;">003</td> <td style="min-width:74px; max-width:74px;left: 30px; width: 74px; overflow:hidden;background-color:#fff;position:absolute;z-index:1;">自动表格</td> <td style="min-width: 100px; max-width: 100px; width: 100px;" >56454自动</td> <td style="min-width: 100px; max-width: 100px; width: 100px;" >56454自动</td> <td style="min-width: 100px; max-width: 100px; width: 100px;" >56454自动</td> <td style="min-width: 100px; max-width: 100px; width: 100px;" >56454自动</td> <td style="min-width: 100px; max-width: 100px; width: 100px;" >56454自动</td> <td style="min-width: 100px; max-width: 100px; width: 100px;" >最后一列</td> </tr> <tr> <td style="min-width:30px; max-width:30px; left:0; width:30px; overflow:hidden; background-color:#fff;position:absolute;z-index:1;">004</td> <td style="min-width:74px; max-width:74px; left: 30px; width: 74px; overflow:hidden;background-color:#fff;position:absolute;z-index:1;">自动表格</td> <td style="min-width: 100px; max-width: 100px; width: 100px;" >56454自动</td> <td style="min-width: 100px; max-width: 100px; width: 100px;" >56454自动</td> <td style="min-width: 100px; max-width: 100px; width: 100px;" >56454自动</td> <td style="min-width: 100px; max-width: 100px; width: 100px;" >56454自动</td> <td style="min-width: 100px; max-width: 100px; width: 100px;" >56454自动</td> <td style="min-width: 100px; max-width: 100px; width: 100px;" >最后一列</td> </tr> <tr> <td style="min-width:30px; max-width:30px; left:0; width:30px; overflow:hidden; background-color:#fff;position:absolute;z-index:1;">005</td> <td style="min-width:74px; max-width:74px; left: 30px; width: 74px; overflow:hidden;background-color:#fff;position:absolute;z-index:1;">自动表格</td> <td style="min-width: 100px; max-width: 100px; width: 100px;" >56454自动</td> <td style="min-width: 100px; max-width: 100px; width: 100px;" >56454自动</td> <td style="min-width: 100px; max-width: 100px; width: 100px;" >56454自动</td> <td style="min-width: 100px; max-width: 100px; width: 100px;" >56454自动</td> <td style="min-width: 100px; max-width: 100px; width: 100px;" >56454自动</td> <td style="min-width: 100px; max-width: 100px; width: 100px;" >最后一列</td> </tr> <tr> <td style="min-width:30px; max-width:30px; left:0; width:30px; overflow:hidden; background-color:#fff;position:absolute;z-index:1;">006</td> <td style="min-width:74px; max-width:74px; left: 30px; width: 74px; overflow:hidden;background-color:#fff;position:absolute;z-index:1;">自动表格</td> <td style="min-width: 100px; max-width: 100px; width: 100px;" >56454自动</td> <td style="min-width: 100px; max-width: 100px; width: 100px;" >56454自动</td> <td style="min-width: 100px; max-width: 100px; width: 100px;" >56454自动</td> <td style="min-width: 100px; max-width: 100px; width: 100px;" >56454自动</td> <td style="min-width: 100px; max-width: 100px; width: 100px;" >56454自动</td> <td style="min-width: 100px; max-width: 100px; width: 100px;" >最后一列</td> </tr> <tr> <td style="min-width:30px; max-width:30px; left:0; width:30px; overflow:hidden; background-color:#fff;position:absolute;z-index:1;">007</td> <td style="min-width:74px; max-width:74px; left: 30px; width: 74px; overflow:hidden;background-color:#fff;position:absolute;z-index:1;">自动表格</td> <td style="min-width: 100px; max-width: 100px; width: 100px;" >56454自动</td> <td style="min-width: 100px; max-width: 100px; width: 100px;" >56454自动</td> <td style="min-width: 100px; max-width: 100px; width: 100px;" >56454自动</td> <td style="min-width: 100px; max-width: 100px; width: 100px;" >56454自动</td> <td style="min-width: 100px; max-width: 100px; width: 100px;" >56454自动</td> <td style="min-width: 100px; max-width: 100px; width: 100px;" >最后一列</td> </tr> <tr> <td style="min-width:30px; max-width:30px; left:0; width:30px; overflow:hidden; background-color:#fff;position:absolute;z-index:1;">008</td> <td style="min-width:74px; max-width:74px; left: 30px; width: 74px; overflow:hidden;background-color:#fff;position:absolute;z-index:1;">自动表格</td> <td style="min-width: 100px; max-width: 100px; width: 100px;" >56454自动</td> <td style="min-width: 100px; max-width: 100px; width: 100px;" >56454自动</td> <td style="min-width: 100px; max-width: 100px; width: 100px;" >56454自动</td> <td style="min-width: 100px; max-width: 100px; width: 100px;" >56454自动</td> <td style="min-width: 100px; max-width: 100px; width: 100px;" >56454自动</td> <td style="min-width: 100px; max-width: 100px; width: 100px;" >最后一列</td> </tr> <tr> <td style="min-width:30px; max-width:30px; left:0; width:30px; overflow:hidden; background-color:#fff;position:absolute;z-index:1;">009</td> <td style="min-width:74px; max-width:74px; left: 30px; width: 74px; overflow:hidden;background-color:#fff;position:absolute;z-index:1;">自动表格</td> <td style="min-width: 100px; max-width: 100px; width: 100px;" >56454自动</td> <td style="min-width: 100px; max-width: 100px; width: 100px;" >56454自动</td> <td style="min-width: 100px; max-width: 100px; width: 100px;" >56454自动</td> <td style="min-width: 100px; max-width: 100px; width: 100px;" >56454自动</td> <td style="min-width: 100px; max-width: 100px; width: 100px;" >56454自动</td> <td style="min-width: 100px; max-width: 100px; width: 100px;" >最后一列</td> </tr> <tr> <td style="min-width:30px; max-width:30px; left:0; width:30px; overflow:hidden; background-color:#fff;position:absolute;z-index:1;">010</td> <td style="min-width:74px; max-width:74px; left: 30px; width: 74px; overflow:hidden;background-color:#fff;position:absolute;z-index:1;">自动表格</td> <td style="min-width: 100px; max-width: 100px; width: 100px;" >56454自动</td> <td style="min-width: 100px; max-width: 100px; width: 100px;" >56454自动</td> <td style="min-width: 100px; max-width: 100px; width: 100px;" >56454自动</td> <td style="min-width: 100px; max-width: 100px; width: 100px;" >56454自动</td> <td style="min-width: 100px; max-width: 100px; width: 100px;" >56454自动</td> <td style="min-width: 100px; max-width: 100px; width: 100px;" >最后一列</td> </tr> </table> </div> </div> <div style="background-color:#eee;overflow:hidden;top:150px; width:100%; z-index:2;position:absolute;"> <div style="margin-left:108px; width:auto;overflow-x:scroll;overflow-y:hidden;" onscroll='divScroll(this);'> <div style="width:630px; height:1px;"></div> </div> </div> </div> <div id="scrollDiv_y" style="display:block; overflow-x:hidden; overflow-y:scroll; position:absolute; top:22px; right:0px; height:118px; padding-bottom:10px;" onscroll='divYScroll(this);'> <div style="width:1px; height:194px;"></div> </div> </div> </div> </body> </html>
1. 전체 구조:
페이지의 기본 요소는 DIV TABLE입니다. 고정 열은 절대 위치 지정으로 고정됩니다. 각 열은 가로 및 세로 스크롤 막대 문제를 해결하기 위해 테이블의 머리글과 본문을 지정해야 합니다. 막대는 각각 두 개의 DIV 레이어로 래핑되어 있으며 가상 방법을 채택하고 JS 제어를 통해 고정 위치에 고정되어 일반 DIV 스크롤 막대의 효과를 시뮬레이션합니다.
2. 포지셔닝:
고정 열은 절대적으로 위치해야 하며 왼쪽 변위는 왼쪽 속성을 통해 제어됩니다. 고정 열이 위에 떠 있도록 하려면 z-index를 1로 설정하세요. 수직 스크롤 바가 있을 때 정상적인 표시를 보장하려면 테이블 본문의 외부 DIV가 절대 위치에 있으므로 스크롤 바도 절대 위치에 있어야 합니다. 또한 테이블 헤더, 테이블 본문 및 스크롤 막대의 내부 DIV는 margin-left 속성을 사용하여 왼쪽 여백을 제어하고 고정 열의 오프셋을 자유롭게 유지합니다.
2. 너비 계산:
각 열의 너비는 고정된 값으로 지정해야 하며, 주의할 점은 min-width 및 max-width 속성이 너비 값과 동일하다는 것입니다. 헤더 및 본문 레이어 DIV의 콘텐츠, 너비는 자동, 적응형 테이블 너비, 외부 DIV 너비는 100%, 가장 바깥쪽 DIV는 오른쪽 패딩 속성을 통해 오른쪽 내부 여백을 제어하여 수직 스크롤 막대의 위치를 자유롭게 유지합니다.
3. 높이 계산:
절대 위치 지정이 있기 때문에 전체 테이블 구성 요소의 높이를 지정해야 하며, 이를 계산하려면 세로 스크롤 막대의 상단 값도 계산해야 합니다.
4. 스크롤바:
이 솔루션의 두드러진 특징은 테이블과 너비가 동일하고 높이가 1픽셀인 DIV를 통해 테이블 본문 DIV의 가로 스크롤 막대를 시뮬레이션하는 가상 스크롤 막대입니다. 스크롤 바. 이 형식을 채택한 이유는 가로 스크롤 막대를 이렇게 처리하면 더 아름답기 때문입니다. 세로 스크롤 막대를 이렇게 처리한 후에는 테이블 헤더와 테이블 본문의 외부 DIV 너비를 계산할 필요가 없습니다. 그렇지 않으면 스크롤 막대가 있는 경우 테이블 헤더의 세로 스크롤 막대 너비가 가로 스크롤 막대에서 벗어나야 합니다. 그렇지 않으면 정렬할 수 없습니다. 이 계산은 복잡하지 않지만 있습니다. 어떤 경우에는 문제가 발생하는데, 여기서는 자세히 설명하지 않겠습니다.
5. 스크롤 이벤트:
테이블 본체의 스크롤바가 숨겨져 있기 때문에 마우스 휠이 작동하지 않으므로 JS를 사용하여 마우스 휠 이벤트를 처리해야 합니다. 이 글의 샘플 코드는 일반 브라우저와 호환됩니다. 여기서 중요한 점은 onmousewheel과 onwheel 이벤트가 동시에 작성된다는 것입니다. onmousewheel은 IE와 호환되므로 스크롤 거리를 계산할 때 deltaY와 WheelDelta 속성의 차이에 주의하세요.
6. 장점과 단점 분석:
이 글에서는 원리를 명확하게 설명하는 데 중점을 두었습니다. 현실적으로는 매우 복잡합니다. 이 디자인은 브라우저 호환성과 다양한 시나리오의 호환성을 포함하여 많은 호환성을 고려합니다. 요구 사항이 단순하다면 단순화할 여지가 있습니다.
이 솔루션의 장점은 컴포넌트를 만들려는 경우 HTML 구조가 간단하고 테이블 헤더와 테이블 본문이 모두 TABLE이므로 JS 제어 코드가 매우 깔끔하고 유지 관리가 쉽다는 것입니다. 단점은 너무 많은 계산이 필요하다는 것입니다. 우리는 이 솔루션이 구성 요소 개발에 더 적합하다고 생각하며 정적 페이지는 약간 까다롭습니다.
위 내용은 이 글의 전체 내용입니다. 모두 마음에 드셨으면 좋겠습니다.