时间:2021-05-26
现如今,我们总是在无止境的刷。刷微博、刷抖音、刷沸点......一次次丝滑下拉体验的背后却是前端攻城狮的用心。
本篇讨论基于 Vue.js 的列表无限下拉实践。
我们的目标就是:让列表下拉纵享丝滑,而不是像以往的下拉就 loading 等待的体验。
咱还是用 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,它在 Github 上又 2.5k+ 的 stars。类比于 react 的 react-virtualized 库。
大量的 DOM 元素会使得我们的网页非常“重”。当 DOM 元素超过 1500 至 2000 个的时候,页面就开始又延迟,尤其是在小型的、性能差的设备上尤为明显。
想象一下,有一个无线滚动的页面,你不断的下拉,它实际上可能形成了上万个 DOM 元素,每个元素还包含子节点,这样将消耗巨大的性能。
Virtual scrollers 正是来解决这个问题的。
如上图,已经表示的很清楚了。列表分为可见区域和缓冲区域,超出这个范围的列表 DOM 都将被删除。
好啦,准备工作已就绪,Let`s get it!
// 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 是 virtual-list 的属性,为此我们需要新建一个 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(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如何?只要你不是疯狂下拉,基本上感受不到 loading 的过程~
用户不会希望每下拉十条结果就要等待新的十条结果加载出来!所以我们需要有缓冲区,还未下拉到底的时候就预判它到底然后提前加载。这便是丝滑体验的内核。
当然不在视图区和缓冲区的 DOM 都将被删除,这也是页面不形成大量 DOM 元素的精髓。
这样动态的处理列表的确是编程人员的一种智慧和用心。
你可以把 项目 克隆到本地再体会一下。以上便是本次分享~
以上就是Vue 虚拟列表的实现示例的详细内容,更多关于Vue 虚拟列表的资料请关注其它相关文章!
声明:本页内容来源网络,仅供用户参考;我单位不保证亦不表示资料全面及准确无误,也不保证亦不表示这些资料为最新信息,如因任何原因,本网内容或者用户因倚赖本网内容造成任何损失或损害,我单位将不会负任何法律责任。如涉及版权问题,请提交至online#300.cn邮箱联系删除。
今天我们继续来说说Vue,目前一直在自学Vue然后也开始做一个项目实战,我一直认为在实战中去发现问题然后解决问题的学习方式是最好的,所以我在学习一些Vue的理论
项目下载地址vue-cli多页面多路由项目示例:vue+webpack+vue-router+vuex+mock+axiosUsageThisisaprojec
vue要绑定下拉列表会稍微有点不同。因为下拉列表不是一个标签能搞掂的。原生的html写法如下Vue.jsReact.jsAngular.js通常下拉列表会用到两
首先列表内容还是与之前的列表内容类似,不过此处我们会采用Vue中数据请求的方式来实现数据的增删。那么我们使用的Vue第三方组件就是vue-resource,vu
最近重读Vue官方文档,在列表的排序过渡这一小节,文档提到,组件有一个特殊的地方,不仅可以实现进入和离开动画,还可以改变定位,官网示例如下:例子中实现的效果看起