Говоря о реализации компонентов таблицы: фиксированные заголовки и фиксированные столбцы

CSS внешний фреймворк
Говоря о реализации компонентов таблицы: фиксированные заголовки и фиксированные столбцы

Во фронтенд-разработке табличный компонент является относительно одним из наиболее сложных компонентов. Основная причина в том, что у всех разные потребности в табличном компоненте. Я никогда не видел табличного компонента, который мог бы удовлетворить все потребности.

С точки зрения бизнес-сценариев табличные компоненты можно разделить на три типа:

  • Класс Bootstrap: таблица, которая может быть реализована с помощью CSS, в основном используется на страницах класса представления информации.
  • Средний и внутренний классы: основное внимание уделяется презентации, редактирование осуществляется с помощью кнопок, в основном используемых в средних и внутренних системах. Большая демаркационная точка по сравнению с таблицами Bootstrap заключается в том, что они имеют такие функции, как фиксированные заголовки таблиц и фиксированные столбцы.
  • Класс Excel: Фокус на редактировании, в основном онлайн-сценарию редактирования данных, которые являются относительно нишами. Этот тип табличного компонента имеет высокие требования к производительности. По сравнению с предыдущими двумя, он имеет некоторые уникальные функции: например, дважды щелкните встроенные редактирование, фиксированные строки и другие функции.

Для требований, применимых к таблицам, подобным Bootstrap, рекомендуется использовать методы, предоставляемые Bootstrap напрямую. К табличным компонентам среднего и фонового классов предъявляется несколько общих требований:

  1. Фиксированный заголовок таблицы
  2. фиксированный столбец
  3. развернуть строку
  4. Сортировка заголовков таблиц, фильтрация заголовков таблиц, многоуровневые заголовки таблиц
  5. один выбор, множественный выбор

Наиболее интересные из этих функций должны относиться к реализации фиксированных заголовков таблиц и фиксированных столбцов.Эта статья в основном используется для описания различных методов реализации этих двух характеристик и того, какой метод реализации следует выбрать.

Содержимое и примеры в этой статье не используют какую-либо структуру, если вы умеете использовать HTML, CSS и jQuery, вы можете читать и понимать в теории.

Начните с простой формы

Чтобы снизить для вас порог чтения, для реализации обеих функций подготовлены онлайн-примеры. Каждый онлайн-пример выполняется путем изменения одной из простейших таблиц Bootstrap 3.0, которую можно найти по адресуПосмотреть здесь.

Реализация фиксированного заголовка таблицы

Если данные в таблице имеют полосу прокрутки, то пользователь захочет, чтобы заголовок таблицы при прокрутке фиксировался вверху, иначе нет возможности увидеть смысл данных ячейки.

браузер<table>Полоса прокрутки не может отображаться, даже если полоса прокрутки может отображаться, нет никакого способа добиться этого<thead>не листай,<tbody>можно прокручивать.

Простейшая идея состоит в том, чтобы использовать два<table>, один используется для отображения заголовка таблицы, а другой используется для отображения содержимого таблицы. Используйте другой элемент для переноса содержимого таблицы<table>, установитьoverflow: autoЧтобы отобразить полосу прокрутки. Метод реализации показан на следующем рисунке:

По этой идее быстро реализуется версия, можно нажатьПосмотреть здесь.

В этой версии есть очень очевидная проблема, то есть ширина столбцов заголовка таблицы и содержимого таблицы несовместимы, и будут дислокации. Причины дислокации следующие: содержимое таблицы должно отображать полосу прокрутки, а заголовок таблицы не должен отображать полосу прокрутки, поэтому их ширина создает разницу в ширине. Общей практикой является добавление дополнительного элемента в заголовок таблицы, чтобы компенсировать эту разницу в ширине, которая обычно называется Gutter.

Модифицированная реализация показана на следующем рисунке:

Исправленная версия может быть непосредственноПосмотреть онлайн, Результаты, как показано ниже:

Помимо желоба, есть еще несколько ситуаций, которые необходимо объяснить, поэтому добавлены четыре стрелки, а некоторые пояснения даны ниже.

Реализация желоба

Определение Gutter см. в описании выше Gutter находится в позиции стрелки 1. Метод реализации см. в элементе th.gutter в примере HTML и в определении стиля th.gutter в CSS. В реальных сценариях ширина Gutter будет меняться в зависимости от браузеров и операционных систем, и эту ширину необходимо вычислять динамически. Код реализации выглядит следующим образом:

<th class="gutter"></th>
/** Header 右侧的空隙 */
.custom-table th.gutter {
  width: 15px;
  padding: 0;
}

Реализация правой границы

Правая граница относится к положению стрелки 2. Из-за наличия Gutter фактическая ширина содержимого таблицы меньше ширины полосы прокрутки, и граница с правой стороны таблицы не может отображаться нормально. В этом примере используются псевдоэлементыbeforeДобавлена ​​правая граница для самого внешнего элемента. Код реализации выглядит следующим образом:

/** 右侧边框 */
.custom-table::before {
  content: "";
  display: block;
  position: absolute;
  top: 0;
  bottom: 0;
  right: 0;
  border-right: 1px solid #ddd;
}

Реализация нижней границы

Нижняя граница находится в позиции стрелки 3, а исходная нижняя граница отображается в<table>начальство,<table>После добавления полосы прокрутки к родительскому элементу это приведет к тому, что<table>Нижняя граница не отображается. Поэтому вам нужно добавить нижнюю границу к самому внешнему элементу, чтобы компенсировать отсутствие этой границы. В этом примере используются псевдоэлементыbeforeДобавлена ​​правая граница для самого внешнего элемента. Код реализации выглядит следующим образом:

/** 底部边框 */
.custom-table::after {
  content: "";
  display: block;
  height: 0px;
  position: relative;
  top: -1px;
  border-bottom: 1px solid #ddd;
}

Постоянная ширина столбца

Поскольку заголовок таблицы и содержимое таблицы теперь являются двумя отдельными<table>элементы, синхронизация ширины столбца обоих становится проблемой. В этом примере, просто установивtable-layoutАтрибут исправлен для решения проблемы.Код реализации выглядит следующим образом:

.custom-table .table {
  table-layout: fixed;
  margin-bottom: 0;
}

оtable-layout, вы можете обратиться кэта статья. В двух словах два значения макета таблицы работают следующим образом:

  • auto: ширина ячейки будет регулироваться в соответствии с содержимым.
  • исправлено: по<table>или<col>Он определяется свойством ширины первой строки, если нет, то определяется шириной ячейки в первой строке.

Простая установка фиксированного макета таблицы не может решить проблему. Измененный стиль может по-прежнему вызывать смещение. Вы можете обратиться кэтот пример. В этом примере только первая строка первой строки в содержимом таблицыtdПри добавлении атрибута ширины заголовок и содержимое таблицы теряются.

согласно сtable-layoutСпособ работы, принцип решения этой задачи относительно прост: для<table>Увеличивать<col>элемент, в<col>Установите атрибут ширины элемента для динамической синхронизации заголовка и содержимого таблицы.<col>Настройка ширины элемента.

Из-за нехватки места я не буду повторять, как код реализует эту функцию, если вам интересно, вы можете попробовать это сами.

фиксированный столбец

Фиксированный заголовок таблицы достигается путем разделения заголовка таблицы и содержимого таблицы на две части.<table>Для достижения этого реализация фиксированных столбцов по существу является клонированием заголовка таблицы и содержимого таблицы, необходимых для достижения фиксированного столбца. Принцип реализации показан на следующем рисунке Заголовок и тело таблицы для фиксированных столбцов представлены темным цветом:

Чтобы упростить этот пример, реализация этого примера добавляет два предварительных условия:

  1. Высота строки каждой строки таблицы одинакова.
  2. Столбцы с фиксированными столбцами имеют фиксированную ширину, которая равна 80 .

Реализация фиксированных столбцов зависит от реализации фиксированных заголовков, поэтому она изменена на примере фиксированных заголовков.Посмотреть онлайн. Пример эффекта показан на следующем рисунке:

Есть три шага для достижения этого эффекта, как показано стрелками на рисунке выше:

  1. Визуализировать фиксированные столбцы
  2. Синхронизированные события прокрутки
  3. Синхронизация эффекта наведения

Визуализировать фиксированные столбцы

Сначала визуализируйте заголовок таблицы и содержимое таблицы фиксированного столбца с помощью HTML:

<div class="custom-table--fixed-wrapper">
  <div class="custom-table--header-wrapper">
    <table class = "table table-bordered">
      <tr>
        <th> Game ID </th>
      </tr>
    </table>  
  </div>

  <div class="custom-table--body-wrapper is-fixed" style="height: 300px;">
    <table class = "table table-hover table-bordered">
      <tr>
        <td> 1 </td>
      </tr>
      <tr>
        <td> 2 </td>
      </tr>
      <tr>
        <td> 13 </td>
      </tr>
      <tr>
        <td> 1 </td>
      </tr>
      <tr>
        <td> 2 </td>
      </tr>
      <tr>
        <td> 13 </td>
      </tr>
      <tr>
        <td> 1 </td>
      </tr>
      <tr>
        <td> 2 </td>
      </tr>
      <tr>
        <td> 13 </td>
      </tr>
      <tr>
        <td> 1 </td>
      </tr>
      <tr>
        <td> 2 </td>
      </tr>
      <tr>
        <td> 13 </td>
      </tr>
    </table>
  </div>
</div>

Затем добавьте следующие стили для фиксированного столбца:

.custom-table--body-wrapper.is-fixed {
  overflow-y: hidden;
}

.custom-table--fixed-wrapper {
  box-shadow:4px 0px 4px rgba(0, 0, 0, 0.1);
  position: absolute; 
  left: 0;
  top: 0;
  bottom: 0;
  width: 81px;
  background-color: #fff;
}

.custom-table td, .custom-table th {
  white-space: nowrap;
  overflow: hidden;
  height: 42px;
  padding: 2px !important;
}

Синхронизированные события прокрутки

Поскольку полоса прокрутки фиксированного столбца и тело таблицы независимы, при прокрутке тела таблицы ее необходимо синхронизировать с полосой прокрутки содержимого таблицы фиксированного столбца. Код, реализованный с помощью jQuery, выглядит следующим образом:

// 同步两边的滚动
$('.custom-table--body-wrapper').on('scroll', function(event) {
    var scrollTop = $(this).prop('scrollTop');
  $('.custom-table--body-wrapper.is-fixed').prop('scrollTop', scrollTop);
});

Синхронизация эффекта наведения

Синхронизация эффекта наведения будет немного более проблематичной, потому что помимо наведения тела таблицы на фиксированный столбец, наведение на фиксированный столбец также повлияет на тело таблицы. Поскольку эффект наведения Bootstrap использует:hoverДля этого вам нужно добавить класс, использующий наведение:

.custom-table tbody > tr.hover > td {
  background-color: #f5f5f5;
}

Код JavaScript для реализации эффекта синхронного наведения выглядит следующим образом:

var getRowIndex = function(event) {
  var target = event.target;
  if (target.tagName === 'TR') {
    return $(target).index();
  } else {
    return $(event.target).parent('tr').index();
  }
};

// 同步两边的 hover 效果
$('.custom-table--body-wrapper tr').hover(function(event) {
  var index = getRowIndex(event);
    $('.custom-table--body-wrapper tr:nth-child(' + (index + 1) + ')').addClass('hover');
}, function(event) {
    var index = getRowIndex(event);
    $('.custom-table--body-wrapper tr:nth-child(' + (index + 1) + ')').removeClass('hover');
});

Разразиться

Этот пример имеет два ограничения, которые будут просто вызваны:

  1. Высота строки каждой строки таблицы одинакова: поскольку содержимое таблицы фиксированного столбца в этом примере отображает только один столбец, высота строки фиксированного столбца управляется этим столбцом. Однако высота строки в основной части таблицы контролируется всеми строками, и синхронизация высоты двух несвязанных элементов не может быть достигнута с помощью CSS.
  2. Фиксированные столбцы столбцов имеют фиксированную ширину: поскольку ширина столбца тела таблицы определяется шириной таблицы, фиксированный столбец отображает только один столбец, и также невозможно синхронизировать ширину столбца, соответствующую телу таблицы, с помощью CSS.

Чтобы обойти эти два ограничения, обычно есть два варианта:

  1. Динамически синхронизируйте высоту строки и ширину столбца слева и справа: преимущество в том, что производительность лучше, и будут отображаться только те столбцы, которые необходимо отобразить. Недостатком является то, что трудно контролировать время синхронизации высоты строк и ширины столбцов, и будут некоторые крайние случаи, которые приведут к ошибкам, например смещение, вызванное несовместимой шириной столбцов и высотой строк.
  2. Фиксированный столбец, наложенный на тело таблицы, отображает все столбцы: преимущество в том, что нет необходимости динамически синхронизировать высоту строки и ширину столбца, что позволяет браузеру самостоятельно контролировать высоту строки и ширину столбца, и это сложно есть неуместные ошибки. Недостаток также очевиден, то есть в сцене с большим объемом данных или сложным содержимым рендеринга в таблице это приведет к слишком большому времени рендеринга, что приведет к определенным проблемам с производительностью.

Кстати, табличный компонент не обязательно должен преодолевать эти два ограничения, иногда необходимо добавить эти два ограничения, что зависит от реального бизнес-сценария. Для табличных компонентов, подобных Excel, фиксированная высота строки является основой для обеспечения производительности компонента, и это ограничение также снижает сложность реализации некоторых других функций.

напиши в конце

Для фронтенд-программистов реализация сложных компонентов всегда была узкоспециализированной работой. С одной стороны, это связано со сложностью реализации, а с другой стороны, из-за слишком низкого коэффициента ввода-вывода лучше напрямую использовать продукты с открытым исходным кодом или коммерческие продукты.

Если вы намерены реализовать табличный компонент самостоятельно, я надеюсь, что эта статья сможет вам помочь. Если у вас есть какие-либо вопросы по содержанию статьи, пожалуйста, оставьте сообщение прямо в области комментариев к статье.

Наконец, спасибо за ваше терпение, чтобы прочитать эту статью.