После недавнего запуска проекта продукт выдвинул требование адаптивного содержимого по ширине столбца для списка на главной странице, то есть ширина столбца определяется ячейкой с самым широким содержимым в текущем столбце (кнопка содержимое ячейки не переносится). Таблица в проекте использует компонент таблицы element-ui, который является очень мощным и отвечает различным потребностям, таким как фиксированные столбцы, фиксированные заголовки, расширенные строки и многое другое. Однако в условиях такого спроса кажется, что прямой поддержки элементов конфигурации нет.
Идея 1: Подходящий атрибут
Первая реакция на это требование состояла в том, чтобы подумать о приспособленном атрибуте, упомянутым в документе элемента. После тщательно рассмотрения документации я обнаружил, что это свойство включено по умолчанию. На самом деле точное значение fit состоит в том, что все столбцы заполняют контейнер, где находится вся таблица. Соответствующий исходный код атрибута FIT для FIT заключается в следующем:
//没有指定宽度的列
let flexColumns = flattenColumns.filter((column) => typeof column.width !== 'number');
const fit = this.fit;
const bodyWidth = this.table.$el.clientWidth;
let bodyMinWidth = 0;
if (flexColumns.length > 0 && fit) {
//获取表格的最小宽度
flattenColumns.forEach((column) => {
bodyMinWidth += column.width || column.minWidth || 80;
});
const scrollYWidth = this.scrollY ? this.gutterWidth : 0;
//如果最小宽度小于容器宽度,即没有撑满容器
if (bodyMinWidth <= bodyWidth - scrollYWidth) {
this.scrollX = false;
const totalFlexWidth = bodyWidth - scrollYWidth - bodyMinWidth;
//把富余的宽度均分给除第一列的其他列,剩下来的给第一列(避免宽度均分的时候除不尽)
if (flexColumns.length === 1) {
flexColumns[0].realWidth = (flexColumns[0].minWidth || 80) + totalFlexWidth;
} else {
const allColumnsWidth = flexColumns.reduce((prev, column) => prev + (column.minWidth || 80), 0);
const flexWidthPerPixel = totalFlexWidth / allColumnsWidth;
let noneFirstWidth = 0;
flexColumns.forEach((column, index) => {
if (index === 0) return;
const flexWidth = Math.floor((column.minWidth || 80) * flexWidthPerPixel);
noneFirstWidth += flexWidth;
column.realWidth = (column.minWidth || 80) + flexWidth;
});
flexColumns[0].realWidth = (flexColumns[0].minWidth || 80) + totalFlexWidth - noneFirstWidth;
}
}else{
//fit=false,对没有设置宽度的列宽度设为80
flattenColumns.forEach((column) => {
if (!column.width && !column.minWidth) {
column.realWidth = 80;
} else {
column.realWidth = column.width || column.minWidth;
}
bodyMinWidth += column.realWidth;
});
}
Из исходного кода видно, что это свойство не является адаптивным содержимым нужной нам ширины столбца Этот код также является основной логикой updateColumnsWidth. Подводя итог, ширина столбца и содержимое не связаны внутри el-table. Таким образом, желательный адаптивный контент по ширине столбца может быть выполнен только извне.
Идея 2: макет таблицы: авто
Поскольку el-table не поддерживает элементы конфигурации, можно ли решить ее с точки зрения CSS? Я думаю, что у нативной таблицы есть такая функция, и вкратце представлю режим компоновки нативной таблицы.
CSS-свойство table-layout определяет алгоритм, используемый для размещения ячеек таблицы, строк и столбцов.
авто Большинство браузеров используют алгоритм автоматической компоновки таблиц для компоновки таблиц. Ширина таблиц и ячеек зависит от содержимого, которое они содержат.
фиксированный Ширина таблиц и столбцов задается шириной таблицы, а ширина столбца определяется только ячейками в первой строке столбца. В текущем столбце строка после ячейки не влияет на ширину всего столбца. При «фиксированном» макете вся таблица может быть проанализирована и отображена после загрузки ее первой строки. Это может ускорить рендеринг для «автоматического» метода автоматической компоновки,Однако содержимое последующих ячеек не будет адаптироваться к текущей ширине столбца.. Любая ячейка с переполненным содержимым может использовать свойство переполнения, чтобы контролировать, разрешено ли содержимое переполняться.
el-table использует второйtable-layout:fixed
Mode, можно ли этого добиться, изменив макет таблицы на автоматический? После попытки не работает. Одна из причин заключается в том, что для реализации фиксированных заголовков и фиксированных столбцов el-table необходимо создавать дополнительные таблицы. Это затрудняет управление синхронизацией ширины столбца между несколькими таблицами. Решение этой проблемы заключается в следующем:<table>
Увеличивать<col>
элемент, в<col>
Установите атрибут ширины элемента для динамической синхронизации заголовка и содержимого таблицы.<col>
Настройки ширины на элементе. Это решение точно установленоtable-layout:fixed
под помещение.
Для получения подробной информации, пожалуйста, нажмите на статью босса команды
Если вам нужно только отобразить таблицу в вашем проекте, вы можете рассмотреть возможность использования собственной таблицы.Использование таблицы в нефиксированном режиме очень просто для достижения требований адаптивной ширины столбца. (Рекламный фон Toutiao, на который ссылается продукт для этого требования, является используемой собственной таблицей, но он также имеет много недостатков)
Идея 3: рассчитать ширину столбца вручную
Кажется, что «автоматический» подход не работает, поэтому ширину столбцов необходимо вычислять вручную перед рендерингом. Это нормально для столбцов, содержимое которых представляет собой текст. Типы символов текста делятся на три типа: китайский и английский, цифры и специальные символы, которые отфильтровываются по обычным правилам. Затем умножьте каждый тип символов на размер шрифта и преобразуйте его в определенное соотношение, чтобы получить приблизительную ширину. Распространите весь набор данных таблицы, чтобы получить максимальное значение ширины столбца, которое необходимо адаптировать к содержимому, которое является максимальным значением между ним и шириной заголовка.
getMaxLength (arr) {
return arr.reduce((acc, item) => {
if (item) {
const str = item.toString()
const char = str.match(/[\u2E80-\u9FFF]/g)
const charLen = char ? char.length : 0
const num = str.match(/\d|\./g)
const numLen = num ? num.length : 0
const otherLen = str.length - charLength - numLength
let calcLen = charLen * 1.1 + numLen * 0.65 + otherLen * 0.5
if (acc < calcLen) {
acc = calcLen
}
}
return acc
}, 0)
}
Даже для столбцов текстового типа приведенная выше рассчитанная ширина не является точной шириной. Поскольку шрифты делятся на моноширинные и пропорциональные, большинство китайских шрифтов в Интернете являются моноширинными, например Microsoft Yahei, который используется чаще всего. Но английские шрифты в основном пропорциональные шрифты, и ширина каждой буквы разная.
Суммировать
Поскольку ширина пользовательских столбцов в текущем проекте может быть известна заранее, например, переключатели, раскрывающиеся поля выбора и т. д. Таким образом, ручное вычисление ширины для столбца текстового типа может в основном удовлетворить потребности продукта. В процессе исследования требований я нашел в Интернете адаптивный компонент ширины столбца с открытым исходным кодом, который также является вторичным пакетом на основе el-table, Если вы хотите использовать его напрямую, вы можете обратиться к нему.
Это едва решает проблему, но это явно не идеальное решение.Если у вас есть хорошие предложения или реализации, пожалуйста, прокомментируйте и дайте нам знать.