Решить проблему зависания таблицы больших данных на основе vue

Vue.js

Нажмите на меня, чтобы ознакомиться с демо-версией онлайн (для просмотра используйте компьютер)

Протестировано на компьютере Apple, в браузере Chrome нет заикания, другие браузеры не тестировались, если вы столкнулись с заиканием, обратите внимание на систему и браузер, чтобы облегчить мою последующую оптимизацию, спасибо

Первый взгляд на эффект, всего1000 X 100 = 10WКаждая ячейка в основном не застревает, и каждую ячейку можно редактировать, щелкнув по ней, поддерживая фиксированные заголовки и фиксированные столбцы.

Исходный код проекта на гитхабедумаю, ты можешьStarПожалуйста, дайте мне знать, если у вас есть какие-либо вопросы, спасибо

Решите суть проблемы: в соответствии с видимой областью загрузка горизонтальной прокрутки, загрузка вертикальной прокрутки, контроль количества dom

Предыстория проекта

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

30 месяцев поперечных ячеек, самые 3 года, 36 месяцев, в каждом ряду 36*30=1080 ячеек

Ресурсов по вертикали 100, всего около ️10Вт ячеек, а дальше будет поле ввода и общий инвентарь в каждой ячейке, так что общее количество 20Вт, использование интранета, запрос интерфейса не проблема на все, это может рендерить браузер, я терпеть не могу, и после того, как интерфейс вернется, будет белый экран на десятки секунд, и вся страница застрянет.

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

Предыдущая функция была разработана на основе jquery.Vue и пользовательский интерфейс, используемые для реконструкции проекта, используют ElementUI.Таблица в ElmentUI имеет серьезные проблемы с производительностью, когда объем данных велик.Самая непосредственная производительность заключается в том, что время белого экрана долгое, и это будет нарушение рендеринга

Поэтому я подумал о том, чтобы самостоятельно реализовать форму, чтобы решить проблему застревания.

Реализовать идеи

Таблица разделена, динамически загружается

Таблица разделена по месяцам по горизонтали, каждый месяц имеет отдельную таблицу, а заполнитель div помещается вне таблицы месяцев для управления отображением в соответствии с положением горизонтальной прокрутки.

Вертикальное разделение по ресурсам, также оберните div-заполнитель, динамически загружайте в соответствии с положением прокрутки и всегда держите количество dom в сети.

Динамическое редактирование, создание полей ввода по запросу

Разные теги имеют разную производительность при рендеринге в браузере, например, тег input намного тяжелее, чем span и другие теги, поэтому его нельзя вводить на весь экран.

Решение состоит в том, чтобы щелкнуть ячейку, чтобы отобразить поле ввода, фокус теряется и удаляется, отображение здесь не является элементом управления отображением, а v-if контролирует, загружен ли дом.

декомпозиция кода

железы

<div class="table-head">
          <div class="module"
            v-bind:style="{ transform: 'translateX(' + scrollLeft + 'px)' }"  
            v-for="(item, index) in monthData" v-bind:key="index">
            <table cellspacing="0" cellpadding="0">
              <thead>
                <tr>
                  <td colspan="30">{{item.month}}</td>
                </tr>
                <tr>
                  <td width="100" 
                    v-for="(d_item, d_index) in item.days" v-bind:key="d_index"
                    style="min-width:100px">{{d_item}}</td>
                </tr>
              </thead>
            </table>
          </div>
        </div>

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

 <div class="table-fix-cloumns">
          <div class="module fix-left-top">
            <table width="100" cellspacing="0" cellpadding="0">
              <thead>
                <tr>
                  <td>位置</td>
                </tr>
                <tr>
                  <td>position</td>
                </tr>
              </thead>
            </table>
          </div>
          <div class="module"  v-bind:style="{ transform: 'translateY(' + scrollTop + 'px)' }">
            <table width="100" cellspacing="0" cellpadding="0">
              <thead>
                <tr v-for="(item, index) in projectData" v-bind:key="index">
                  <td>{{item.name}}</td>
                </tr>
              </thead>
            </table>
          </div>
        </div>

тело

<div class="table-body" @scroll="tableScroll" style="height: 300px">
          <div class="module" 
            style="width:3000px;"
            v-for="(item, index) in monthData" v-bind:key="index">
            <div class="content" 
              v-if="Math.abs(index - curModule)  < 3">
              <div class="row"
                style="height:30px"
                v-for="(p_item, p_index) in projectData" 
                v-bind:key="p_index">
                <table width="3000"
                  v-if="Math.abs(p_index - curRow)  < 20"
                  cellspacing="0" cellpadding="0">
                  <tbody>
                    <tr>
                      <td 
                        @click="clickTd(p_index,item.month, d_item, $event)" 
                        v-for="(d_item, d_index) in item.days" v-bind:key="d_index">
                      <span v-if="!originProjectData[p_index][''+item.month][''+d_item]['show']">{{originProjectData[p_index][''+item.month][''+d_item]['last']}}</span>
                      <input
                        @blur="blurTd(p_index,item.month, d_item)"
                        v-if="originProjectData[p_index][''+item.month][''+d_item]['show']"
                        v-model="originProjectData[p_index][''+item.month][''+d_item]['last']"
                        v-focus="originProjectData[p_index][''+item.month][''+d_item]['focus']"/>
                      </td>
                    </tr>
                  </tbody>
                </table>
              </div>
            </div>
          </div>
        </div>

После вышеописанной оптимизации проблема с зависанием стола прекрасно решена, но я не стал инкапсулировать компоненты по следующим причинам

·插件封装后会有很多限制,不能再用vue那种模板写法,用json传入数据,自定义内容不是很灵活
·可以根据自己的应用场景自行修改拓展,代码已经很简洁
·比较懒

Если у вас похожие потребности, вы можете попробовать мою, как вы скажете последнее слово