虚拟列表

虚拟列表允许渲染包含大量元素的列表,而不会损失性能。它与所有与列表一起使用的 Framework7 组件完全兼容,例如搜索栏、无限滚动、下拉刷新、滑动删除(滑动删除)和可排序列表。

虚拟列表布局

虚拟列表 HTML 布局非常简单,它与普通的 列表视图 几乎相同,唯一的区别是:你需要将其留空

<!-- Virtual List -->
<div class="list virtual-list">
  <!-- keep it empty -->
</div>

在哪里

虚拟列表应用方法

现在,当我们有了列表的 HTML,我们需要对其进行初始化。我们需要使用必需的应用方法

app.virtualList.create(参数)- 用参数初始化虚拟列表

  • 参数 - 对象 - 包含虚拟列表参数的对象。必需。
  • 方法返回初始化的虚拟列表实例

app.virtualList.destroy(el)- 销毁虚拟列表实例

  • el - HTML 元素字符串(带有 CSS 选择器)或 对象。要销毁的虚拟列表元素或虚拟列表实例。

app.virtualList.get(el)- 通过 HTML 元素获取虚拟列表实例

  • el - HTML 元素字符串(带有 CSS 选择器)。虚拟列表元素。

方法返回虚拟列表的实例

请注意,虚拟列表容器(列表块元素)应该在初始化的那一刻出现在 DOM 中。

虚拟列表参数

让我们看看所有可用参数的列表

参数类型默认值描述
elHTML 元素
字符串
目标列表块元素。如果为 字符串 - 列表块元素的 CSS 选择器
ulHTML 元素
字符串
列表元素 <ul> 在列表块内。
createUl布尔值true将在虚拟列表块内自动创建 <ul> 元素。如果禁用,则虚拟列表可以在没有 ul > li 结构的任何块元素上使用
items数组包含列表项的数组
rowsBefore数字要渲染到当前屏幕滚动位置之前的行(项目)数量。默认情况下,它等于屏幕上可以容纳的行(项目)数量的两倍
rowsAfter数字要渲染到当前屏幕滚动位置之后的行(项目)数量。默认情况下,它等于屏幕上可以容纳的行(项目)数量
cols数字1每行项目的数量。当与动态高度的虚拟列表一起使用时不兼容
height数字或函数(item)或“auto”

如果为 数字 - 列表项高度(单位为像素)。

如果为 函数,则函数应该返回项的高度。默认情况下,对于 iOS 主题为 44,对于 MD 主题为 48

如果为 "auto",它将自动计算每个项的高度。在这种情况下,它可能会稍微慢一些,但在无法确定或预测项高度时,它仍然好得多

renderItem函数(item)此可选函数允许使用自定义函数来渲染项目 HTML。它可以用来代替 template 参数
renderExternal函数(vl,renderParameters)此可选函数允许使用某种自定义方法来渲染 DOM 项目。在与 Vue/React 插件一起使用(例如)时很有用,可以将 DOM 渲染和操作传递给 Vue/React。renderParameters 包含一个具有以下属性的对象:fromIndextoIndexlistHeighttopPositionitems
emptyTemplate字符串定义列表项模板,用于在传递空数据的情况下
dynamicHeightBufferSize数字1此参数允许您控制具有动态高度的虚拟列表的缓冲区大小(当 height 参数为函数时),作为缓冲区大小乘数
cache布尔值true禁用或启用已渲染列表项的 DOM 缓存。在这种情况下,每个项目只会被渲染一次,所有后续操作都将使用 DOM 元素。如果您的列表项有一些用户交互元素(例如表单元素或滑动删除)或可以被修改,这将非常有用
updatableScroll布尔值当前设备是否更新并处理滚动事件。默认情况下(如果未指定),对于所有 iOS 设备(iOS 版本低于 8)来说都是“false”。
setListHeight布尔值true如果启用,将在列表块上设置高度
showFilteredItemsOnly布尔值false仅显示由方法设置的过滤项的选项method
scrollableParentElHTML 元素
字符串
虚拟列表的可滚动父元素。如果未指定,则它将查找父 <div class="page-content"> 元素
搜索栏
searchByItem函数(query,item,index)将由 搜索栏 使用的搜索函数,它接收搜索查询、项目本身和项目索引。如果项目与搜索查询匹配,则需要返回 true,否则此函数应该返回 false
searchAll函数(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
方法
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 的名称。

事件目标参数描述
itemBeforeInsertvirtualListvirtualList, itemEl, item在将项目添加到虚拟文档片段之前触发事件
vlItemBeforeInsertapp
itemsBeforeInsertvirtualListvirtualList, fragment在删除当前 DOM 列表并插入新文档之前触发事件
vlItemsBeforeInsertapp
beforeClearvirtualListvirtualList, fragment在删除当前 DOM 列表并将其替换为新的文档片段之前触发事件
vlBeforeClearapp
itemsAfterInsertvirtualListvirtualList, fragment在插入包含项目的新的文档片段后触发事件
vlItemsAfterInsertapp

示例

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 mathced 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>