Чен Цзяньбо: игрок в 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()
}
До сих пор производительность челночного фрейма с большим объемом данных была значительно улучшена.