虚拟列表
虚拟列表允许渲染包含大量元素的列表而不损失性能。它与所有与列表配合工作的 Framework7 组件完全兼容,例如搜索栏、无限滚动、下拉刷新、滑动删除(swipe-to-delete)和可排序。
虚拟列表布局
虚拟列表的 HTML 布局非常简单,它与普通列表几乎相同,唯一的区别是你需要将其留空:列表视图 with only difference: you need to leave it empty:
<!-- Virtual List -->
<div class="list virtual-list">
<!-- keep it empty -->
</div>
Where:
virtual-list
- 在使用虚拟列表的任何列表块上需要添加必要的额外类
虚拟列表应用方法
现在,当我们有列表的 HTML 时,我们需要初始化它。我们需要使用必要的应用方法:
app.virtualList.create(参数)- 使用参数初始化虚拟列表
- 参数 - 对象- 虚拟列表参数的对象。必需。
- 方法返回初始化的虚拟列表实例
app.virtualList.destroy(el)- 销毁虚拟列表实例
- el - HTMLElement或字符串(使用 CSS 选择器) 或对象. 要销毁的虚拟列表元素或虚拟列表实例。
app.virtualList.get(el)- 通过 HTML 元素获取虚拟列表实例
- el - HTMLElement或字符串(使用 CSS 选择器)。虚拟列表元素。
方法返回虚拟列表的实例
注意虚拟列表容器(列表块元素)应在初始化时位于 DOM 中。
虚拟列表参数
让我们查看所有可用参数的列表:
参数 | 类型 | 默认 | 描述 |
---|---|---|---|
el | HTMLElement 字符串 | 目标列表块元素。在string - 列表块元素的 CSS 选择器 | |
ul | HTMLElement 字符串 | 列表元素<ul> 内部的列表块中。 | |
createUl | 布尔值 | true | 将自动在虚拟列表块内部创建<ul> 元素。如果禁用,则虚拟列表可用于任何块元素而无需ul > li 结构 |
items | 数组 | 列表项的数组 | |
rowsBefore | 数字 | 在当前屏幕滚动位置之前要渲染的行(项)数量。默认情况下,它等于适合屏幕的行(项)数量的两倍 | |
rowsAfter | 数字 | 在当前屏幕滚动位置之后要渲染的行(项)数量。默认情况下,它等于适合屏幕的行(项)数量 | |
cols | 数字 | 1 | 每行项目数量。在使用动态高度的虚拟列表时不可用 |
高度 | 数字或函数(item)或 "auto" | 如果 如果 如果 | |
renderItem | function(item) | 此可选函数允许使用自定义函数来渲染项目 HTML。它可以用来代替templateparameter | |
renderExternal | function(vl, renderParameters) | 此可选函数允许使用自定义方法来渲染 DOM 项目。在(例如)使用 Vue/React 插件时很有用,可以将 DOM 渲染和操作传递给 Vue/React。renderParameters conaints 对象具有以下属性:fromIndex , toIndex , listHeight , topPosition , items | |
emptyTemplate | 字符串 | 定义当传递空数据时的列表项模板 | |
dynamicHeightBufferSize | 数字 | 1 | 此参数允许控制具有动态高度的虚拟列表的缓冲区大小(当height 参数是函数)作为缓冲区大小乘数 |
cache | 布尔值 | true | 禁用或启用已渲染列表项的 DOM 缓存。在这种情况下,每个项目将只渲染一次,所有进一步的操作都将使用 DOM 元素。如果您的列表项包含一些用户交互元素(如表单元素或滑动删除),或者可以修改 |
updatableScroll | 布尔值 | 当前设备在滚动期间更新和处理滚动事件。默认情况下(如果未指定),对于 iOS 版本小于 8 的所有 iOS 设备,它为 "false"。 | |
setListHeight | 布尔值 | true | 如果启用,将设置列表块的高度 |
showFilteredItemsOnly | 布尔值 | false | 选项仅显示 |
scrollableParentEl | HTMLElement 字符串 | 虚拟列表的滚动父元素。如果未指定,则它将查找父<div class="page-content"> 元素之前插入元素 | |
搜索栏 | |||
searchByItem | function(query, item, index) | 将用于搜索栏的搜索函数,它接收搜索查询、项目本身和项目索引。如果项目与搜索查询匹配,您需要返回true ,否则此函数应返回false | |
searchAll | function(query, items) | 将用于搜索栏的搜索函数,它接收搜索查询和所有项目的数组。您需要遍历项目并返回匹配项目索引的数组 |
虚拟列表方法和属性
所以要创建虚拟列表,我们必须调用:
var virtualList = app.virtualList.create({ /* parameters */ })
初始化虚拟列表后,我们在变量(如virtualList
上面示例中的变量)中具有其初始化实例,带有有用的方法和属性:
属性 | |
---|---|
virtualList.items | 项目数组 |
virtualList.filteredItems | 过滤项目数组(在使用 ".filterItems" 方法后) |
virtualList.domCache | 缓存 DOM 项目的对象 |
virtualList.params | 列表初始化时传递的参数 |
virtualList.el | 虚拟列表目标列表块元素 |
virtualList.$el | 目标列表块元素的 Dom7 实例 |
virtualList.pageContentEl | 父 "page-content" 元素 |
virtualList.$pageContentEl | 父 "page-content" 元素的 Dom7 实例 |
virtualList.currentFromIndex | 当前第一个渲染项目的索引号 |
virtualList.currentToIndex | 当前最后一个渲染项目的索引号 |
virtualList.reachEnd | 布尔属性。如果当前最后一个渲染的项目是所有指定项目的最后一个项目,则等于true 7b8e01: virtualList.filterItems( |
方法 | |
virtualList.filterItems(indexes); | 通过传递要显示的项目索引数组来过滤虚拟列表 |
virtualList.resetFilter(); | 禁用过滤器并再次显示所有项目 |
virtualList.appendItem(item); | 将项目添加到虚拟列表 |
virtualList.appendItems(items); | 将包含项目的数组添加到虚拟列表 |
virtualList.prependItem(item); | 将项目添加到虚拟列表的开头 |
virtualList.prependItems(items); | 将包含项目的数组添加到虚拟列表的开头 |
virtualList.replaceItem(index, item); | 用新项目替换指定索引处的项目 |
virtualList.replaceAllItems(items); | 用新项目的数组替换所有项目 |
virtualList.moveItem(oldIndex, newIndex); | 将虚拟项目从oldIndex移动到newIndex |
virtualList.insertItemBefore(index, item); | 在指定索引之前插入新项目 |
virtualList.deleteItem(index); | 删除指定索引处的项目 |
virtualList.deleteItems(indexes); | 删除指定索引数组中的项目 |
virtualList.deleteAllItems(); | 删除所有项目 |
virtualList.clearCache(); | 清除虚拟列表缓存的DOM元素 |
virtualList.destroy(); | 销毁初始化的虚拟列表并分离所有事件 |
virtualList.update(); | 更新虚拟列表,包括列表大小的重新计算和虚拟列表的重新渲染 |
virtualList.scrollToItem(index); | 通过索引号滚动到指定的虚拟列表项目 |
虚拟列表事件
虚拟列表将在应用和虚拟列表实例上触发以下事件:
虚拟列表实例在自身实例和应用实例上触发事件。应用实例事件名称前缀为vl
.
事件 | Target | 参数 | 描述 |
---|---|---|---|
itemBeforeInsert | virtualList | virtualList, itemEl, item | 事件将在项目添加到虚拟文档片段之前触发 |
vlItemBeforeInsert | app | ||
itemsBeforeInsert | virtualList | virtualList, fragment | 事件将在当前 DOM 列表被移除之前和新的文档插入之前触发 |
vlItemsBeforeInsert | app | ||
beforeClear | virtualList | virtualList, fragment | 事件将在当前 DOM 列表被移除并替换为新的文档片段之前触发 |
vlBeforeClear | app | ||
itemsAfterInsert | virtualList | virtualList, fragment | 事件将在带有项目的新文档片段插入之后触发 |
vlItemsAfterInsert | app |
示例
virtual-list.html
<template>
<div class="page">
<div class="navbar">
<div class="navbar-bg"></div>
<div class="navbar-inner sliding">
<div class="title">Virtual List</div>
<div class="subnavbar">
<form data-search-container=".virtual-list" data-search-item="li" data-search-in=".item-title"
class="searchbar searchbar-init">
<div class="searchbar-inner">
<div class="searchbar-input-wrap">
<input type="search" placeholder="Search" />
<i class="searchbar-icon"></i>
<span class="input-clear-button"></span>
</div>
<span class="searchbar-disable-button">Cancel</span>
</div>
</form>
</div>
</div>
</div>
<div class="searchbar-backdrop"></div>
<div class="page-content">
<div class="block">
<p>Virtual List allows to render lists with huge amount of elements without loss of performance. And it is fully
compatible with all Framework7 list components such as Search Bar, Infinite Scroll, Pull To Refresh, Swipeouts
(swipe-to-delete) and Sortable.</p>
<p>Here is the example of virtual list with 10 000 items:</p>
</div>
<div class="list list-strong list-outline-ios inset-md list-dividers-ios links-list">
<ul>
<li>
<a href="/virtual-list-vdom/">Virtual List VDOM</a>
</li>
</ul>
</div>
<div class="list list-strong list-outline-ios inset-md list-dividers-ios simple-list searchbar-not-found">
<ul>
<li>Nothing found</li>
</ul>
</div>
<div class="list list-strong list-outline-ios inset-md list-dividers-ios virtual-list media-list searchbar-found">
</div>
</div>
</div>
</template>
<script>
export default (props, { $f7, $el, $theme, $onMounted, $onBeforeUnmount }) => {
let items = [];
let virtualList;
for (let i = 1; i <= 10000; i++) {
items.push({
title: 'Item ' + i,
subtitle: 'Subtitle ' + i
});
}
$onMounted(() => {
virtualList = $f7.virtualList.create({
// List Element
el: $el.value.find('.virtual-list'),
// Pass array with items
items,
// Custom search function for searchbar
searchAll: function (query, items) {
var found = [];
for (var i = 0; i < items.length; i++) {
if (items[i].title.toLowerCase().indexOf(query.toLowerCase()) >= 0 || query.trim() === '') found.push(i);
}
return found; //return array with matched indexes
},
// List item render
renderItem(item) {
return `
<li>
<a class="item-link item-content">
<div class="item-inner">
<div class="item-title-row">
<div class="item-title">${item.title}</div>
</div>
<div class="item-subtitle">${item.subtitle}</div>
</div>
</a>
</li>`;
},
// Item height
height: $theme.ios ? 65 : 69,
});
});
$onBeforeUnmount(() => {
virtualList.destroy()
});
return $render;
}
</script>