Решить проблему нехватки памяти при рендеринге апплетом сложных и длинных списков.

Апплет WeChat

обзор проблемы: у нас есть страница отображения списка, которая представляет собой бесконечный поток водопада. Мы инкапсулируем отображаемые элементы в один компонент, давайте назовем его сейчасItem组件. Этот водопадный поток содержит несколько компонентов Item, и этот компонент Item также является относительно сложным, включая различные стили отображения (в любом случае существует около 9 типов в соответствии с разными типами, но есть много узлов рендеринга).В процессе скольжения элемент загружается примерно 30 После -40 это приведет к выходу апплета из-за нехватки памяти, синих и тонких грибочков...[Сухие товары приведены в конце, а также предоставлены небольшие фрагменты программного кода]

Решения:

Компоненты в списке, которые превышают определенную часть экрана, не рендерятся (то есть компоненты выгружаются с помощью wx:if), а рендеринг начинается при достижении критической точки рендеринга, каждый раз следите за тем, чтобы отображалось небольшое количество данных.

Мы сохраняем элементы 15 в нашем проекте.Мы запрашиваем элементы 5 на странице, разделенные на первые 5 элементов, средние 5 элементов и последние 5 элементов.Если он не находится в этом диапазоне, он будет заменен скелетом равного высота и без нагрузки.эти компоненты

Первоначальный метод реализации (последуют более оптимизированные методы)

использоватьмониторинг воздействия, когда элемент подвергается воздействию, запишите высоту элемента и поместите ее в массив как высоту заполнения скелета.Если высота была записана, она не будет записываться снова, при раскрытии передать центральное значение текущий диапазон рендеринга (например, текущий номер страницы, к которой принадлежит элемент, или индекс текущего элемента), а затем обработать его;

Здесь следует отметить одну вещь: если ваш компонент элемента списка сложный, вам необходимо установить записанную высоту на минимальную высоту элемента, когда он будет готов, в противном случае будет определенное время рендеринга при перезагрузке компонента, что вызовет скачки экрана в критическая точка[Это было решено компонентом скелета, который можно игнорировать, как запись в яме]

точка оптимизации

  • Во избежание частых setData и рендеринга сделана функция антишейка, а время 600мс

Недостатки на данный момент

  • При очень быстром скольжении появляется белый экран, потому что мониторинг экспозиции находится в компоненте, а при сверхбыстрой прокрутке компонент не загружается, и мониторинг экспозиции не может быть выполнен, поэтому он не может быть запущен. Подумайте об использовании его здесь.Компоненты скелетаВыполните экспозицию на втором мониторе

итерация оптимизации

  • Поместите компонент скелета как оболочку вне объекта (с помощьюslot), а также контролировать и выставлять напоказ скелет, что может решить вышеуказанные недостатки
  • Сделайте обычный стиль экрана скелета для компонента скелета, вместо чисто белого, он выглядит более элегантно

продолжать искать проблемы

После серии практик возникают некоторые проблемы с вышеприведенным сценарием, где наиболее проблематичным является необходимость передачи текущего индекса, а затем управление отображением данных до и после; здесь для каждогоskeletonДля страницы компонента необходимо повторно написать метод для выполнения этого индекса, а затем отобразить соответствующие данные страницы.

оптимизация

все еще наблюдаюskeletonВыдержка, схема мониторинга здесь становится появляться вверх и вниз по экрануnБлоки контента экрана отображаются, а блоки контента за пределами этого диапазона выгружаются.

как показано на рисунке

основной код

     // 修改了监听是否显示内容的方法,改为前后showNum屏高度渲染
     // 监听进入屏幕的范围relativeToViewport({top: xxx, bottom: xxx})
      let info = SystemInfo.getInfo() //获取系统信息
      let { windowHeight = 667 } = info.source.system
      let showNum = 2 //超过屏幕的数量,目前这个设置是上下2屏
      let listItemContainer = this.createIntersectionObserver()
      listItemContainer.relativeToViewport({ top: showNum * windowHeight, bottom: showNum * windowHeight })
        .observe(`#list-item-${this.data.skeletonId}`, (res) => {
        	// 此处来控制slot展示,详见代码片段
        })
       

галантерейные товары

Нечего сказать, отложи галантерею,Нажмите, чтобы увидеть фрагмент кода

Нажмите, чтобы перейти на гитхаб

Наконец, попробуйте уменьшить количество узлов и оптимизировать код.