оптимизация производительности коробки челнока элемента

внешний интерфейс JavaScript CSS
оптимизация производительности коробки челнока элемента

Чен Цзяньбо: игрок в Hearthstone, которого задержали из-за написания кода

оптимизация производительности коробки челнока элемента

задний план

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

Решения

Ленивая загрузка — компонент InfiniteScroll

Сначала скопируйте исходные компоненты из пакетов/переноса (или измените исходный код, чтобы переупаковать и сохранить приватную библиотеку)

Буду

        v-infinite-scroll="pageDown"
        :infinite-scroll-immediate="false"

добавить в

<el-checkbox-group
        v-show="!hasNoMatch && data.length > 0"
        v-model="checked"
        :size="size"
        :class="{ 'is-filterable': filterable }"
        class="el-transfer-panel__list"
        v-infinite-scroll="pageDown"
        :infinite-scroll-immediate="false"
      >
        <el-checkbox
          class="el-transfer-panel__item"
          :label="item[keyProp]"
          :disabled="item[disabledProp]"
          :key="item[keyProp]"
          v-for="item in filteredData">
            <option-content :option="item"></option-content>
        </el-checkbox>
</el-checkbox-group>

существуетdataопределено вpageSize: 20Используется для указания количества данных на страницеshowData: []Он используется только для отображения, замените данные, которыми действительно нужно манипулировать в приведенном выше коде.filteredData

 v-for="item in showData">

в то же времяwatchсоответствующее обращение в

data (data) {
    const checked = [];
    this.showData = data.slice(0, this.pageSize);

    const filteredDataKeys = this.filteredData.map(
    (item) => item[this.keyProp]
    );
    this.checked.forEach((item) => {
    if (filteredDataKeys.indexOf(item) > -1) {
        checked.push(item);
    }
    });
    this.checkChangeByUser = false;
    this.checked = checked;
},
filteredData (filteredData) {
    this.showData = filteredData.slice(0, this.pageSize);
 }

Начальный номер дисплея здесь произвольно принимается равным 20.

Наконец, добавьте метод, вызываемый при прокрутке вниз

pageDown () {
    const l = this.showData.length;
    const totalLength = this.filteredData.length
    l < totalLength && 
    (this.showData = this.filteredData.slice(0, l + this.pageSize > totalLength ?
    totalLength : l + this.pageSize));
},

При прокрутке вниз длина отображаемых данных увеличивается на 20 (число произвольное), а при превышении отображается максимальная длина.

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

новый вопрос

Ручная прокрутка до конца списка, а затем выполнение операции поиска по-прежнему вызывает проблему зависания.

Передовой

Во время прокрутки данные вверху по-прежнему невидимы, данные не отображаются и не влияют на взаимодействие с пользователем. Поэтому просто отобразите 20 фрагментов данных на текущей странице. мыel-checkbox-groupдобавить одинref=scrollContainerдля работы с полосой прокрутки,

существуетdataОпределите текущее количество страниц вcurIndex: 1

и кpageDownметод изменения

    pageDown () {
      const totalLength = this.filteredData.length
      if((this.curIndex*this.pageSize) < totalLength){
        this.curIndex ++
        const targetLength = this.curIndex * this.pageSize 
        const endPoint = targetLength > totalLength ? totalLength : targetLength
        const startPoint = endPoint - this.pageSize  > 0 ? endPoint - this.pageSize : 0
        this.showData = this.filteredData.slice(startPoint, endPoint);
        this.$refs.scrollContainer.$el.scrollTop = "1px" //滚动条到最上端,衔接下一页,为 0 可能会触发边界问题
      }
    }

Для этого нам также нужно добавить метод page up Команда InfiniteScroll обеспечивает только прокрутку вниз, мы можем расширить эту команду или добавить мониторинг прокрутки самостоятельно.

    mounted(){
        this.$refs.scrollContainer.$el.addEventListener('scroll', this.pageUp)
    },
    beforeDestroy(){
        this.$refs.scrollContainer.$el.removeEventListener('scroll', this.pageUp)
    },

регистрpageUpметод

    pageUp(e){
      if(e.target.scrollTop ===0 && this.curIndex>1){
        this.curIndex --
        const endPoint = this.curIndex * this.pageSize 
        const startPoint = (this.curIndex-1)* this.pageSize 
        this.showData = this.filteredData.slice(startPoint, endPoint);
        const el = this.$refs.scrollContainer.$el
        el.scrollTop = el.scrollHeight - el.clientHeight - 1 // 滚动到最底部,衔接上一页, -1 防止边界问题。
      }
    },

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

    initScroll(){
        this.curIndex = 1
        this.$refs.scrollContainer.$el.scrollTop = 0
    },

В то же время вwatchВыполнить initScroll при соответствующем

    data(){
        ...
        this.initScroll()
        ...
    },
    filteredData (filteredData) {
      ...
      this.initScroll()
    }

До сих пор производительность челночного фрейма с большим объемом данных была значительно улучшена.

3_自定义px_2021-08-04-0.gif