Преамбула
В настоящее время мы всегда находимся в бесконечной чистке зубов. Пролистывание Weibo, Douyin, Boiling Point... За шелковистым выпадающим меню снова и снова скрывается замысел передового осадного льва.
В этой статье обсуждается практика бесконечного выпадающего списка на основе Vue.js.
Наши цели:Сделайте выпадающие списки гладкими и шелковистыми, а не загрузка и ожидание предыдущего раскрывающегося списка.
дизайн
Мы по-прежнему используем Vue CLI для быстрого создания проектов.
Вот главная страница:
// EndlessList.vue
<template>
<div class="endless-scrolling-list">
<!-- 搜索框 -->
<div class="search-box">
<input type="text" v-model="searchQuery"/>
</div>
<p class="center" v-if="results.length == 0 && !loading">
Start typing to search something.
</p>
<!-- 虚拟列表 -->
<virtual-list
:data-key="'pageid'"
:data-sources="results"
:data-component="itemComponent"
:page-mode="true"
/>
<!-- loading -->
<loader v-if="loading" />
</div>
</template>
Суть, конечно,virtual-listкомпоненты~
Для виртуального списка здесь мы используем стороннюю библиотекуVue Virtual Scroll List, который имеет еще 2,5 тысячи звезд на Github. аналогично реагироватьreact-virtualizedбиблиотека.
Большое количество DOM-элементов может сделать наши веб-страницы очень «тяжелыми». Когда элементов DOM больше 1500–2000, страница снова начинает тормозить, особенно на небольших устройствах с низкой производительностью.
Представьте, что у вас есть страница с беспроводной прокруткой, которую вы постоянно прокручиваете, она может фактически формировать десятки тысяч элементов DOM, каждый элемент также содержит дочерние узлы, которые потребляют огромную производительность.
Виртуальные скроллеры здесь, чтобы решить эту проблему.
Как показано на рисунке выше, это очень ясно. Список разделен на видимую область и буферную область, и список DOM за пределами этого диапазона будет удален.
Итак, подготовка завершена, приступим!
выполнить
// imports.js(EndlessList.vue)
import axios from 'axios';
import lodash from 'lodash';
import VirtualList from 'vue-virtual-scroll-list';
import SearchResult from './SearchResult';
import Loader from './Loader';
export default {
name: 'EndlessList',
components: {
VirtualList,
Loader
},
data() {
return {
searchQuery: '',
currentPage: 0,
results: [],
itemComponent: SearchResult,
loading: false
}
},
};
Внедряем сторонние библиотеки axios и loadsh для последующего использования.
в,itemComponentэто свойство виртуального списка, для которого нам нужно создать новыйSearchResultПодкомпоненты, как единицы результатов поиска.
код показывает, как показано ниже:
// SearchResult.vue
<template>
<div class="list-item">
<h3>
{{ source.title }}
</h3>
<div v-html="source.snippet"></div>
</div>
</template>
<script>
export default {
props: {
index: {
// index of current item
type: Number,
},
source: {
type: Object,
default() {
return {};
},
},
},
};
</script>
<style scoped>
.list-item {
padding: 0 10px 20px 10px;
}
.list-item h3 {
margin: 0;
padding-bottom: 10px;
}
</style>
Мы можем получить результаты, выполнив поиск по названию или описанию, запросив данные из Википедии.
// search.js
search(query, page) {
// We prepare the data that the Wikipedia API expects.
const data = {
action: "query",
format: "json",
list: "search",
continue: "-||",
utf8: 1,
srsearch: query,
sroffset: page * 10,
origin: "*",
};
// And then we convert these params TO GET params in the format
// action=query&format=json ...
const params = Object.keys(data)
.map(function(k) {
return data[k] == ""
? ""
: encodeURIComponent(k) + "=" + encodeURIComponent(data[k]);
})
.join("&");
// We prepare the url with the params string
const searchUrl = `https://en.wikipedia.org/w/api.php?${params}`;
// we set loading to true so that we can display the loader
this.loading = true;
// Then we execute the request and concatenate the results
axios.get(searchUrl).then((response) => {
this.results = this.results.concat(response.data.query.search);
// And of course set loading to false to hide the loader.
this.loading = false;
});
}
Метод поиска был написан, а затемперечислить.
- Вызывается, когда пользователь вводит запрос.
- Вызывается при выпадающем списке.
// EndlessList.vue
<script>
export default {
// data() and methods skipped for brevity
watch: {
searchQuery: {
immediate: true,
handler: lodash.debounce(function (newVal) {
if (newVal == "") {
return;
}
this.results = [];
this.currentPage = 0;
this.search(newVal, this.currentPage);
this.search(newVal, this.currentPage + 1);
this.currentPage = 2;
}, 200),
},
},
mounted() {
const vm = this;
window.onscroll = lodash.debounce(function () {
var distanceFromBottom =
document.body.scrollHeight - window.innerHeight - window.scrollY;
if (distanceFromBottom < 400 && vm.searchQuery !== "") {
vm.search(vm.searchQuery, vm.currentPage);
vm.currentPage++;
}
}, 100, {leading: true});
},
}
</script>
Очевидно, когдаsearchQueryПри его изменении мы получаем новые результаты поиска. Конечно, поле ввода здесь также использует функцию защиты от сотрясений.
Еще одна вещь, которую следует отметить, это то, что наш первый поиск загружает две страницы результатов, поэтому у пользователя есть место для прокрутки, чтобы ощущение было плавным.
Мы также добавили функцию защиты от сотрясений в событие прокрутки. Вот вопрос: почемуwindow.onscrollв настройках событияleadingзаtrue?
Затем запускаем программу, чтобы увидеть эффект:
npm run dev
как? Пока вы не тянете вниз как сумасшедший, вы практически не чувствуете процесс загрузки~
резюме
Пользователи не хотят ждать загрузки десяти новых результатов каждый раз, когда они вытягивают десять результатов! Так что нам нужно иметь буфер, прогнозировать его до конца и загружать заранее, когда он не был снесен до конца. Это ядро шелковистого опыта.
Разумеется, DOM, не находящийся в области просмотра и буфере, будет удален, что также является сутью страницы, не образующей большого количества DOM-элементов.
Такой динамический список обработки действительно является своего рода мудростью и намерением программистов.
ты можешь поставитьпроектКлонируйте на локальный и испытайте его снова. Выше это обмен ~
Писать не просто, ставьте лайки и поощряйте! (●'◡'●) Я Энтони из Наггетс, обратите внимание на общедоступный аккаунт [Энтони из Наггетс] и делитесь еще интересными~