收藏
评论

使用虚拟dom,优化长列表显示(上)官方


你好,我是李艺。上节课我们学习了骨架屏技巧,在页面加载动态数据的时候给用户展示一个特定的骨架屏UI,以此提升用户的浏览体验。但页面需要渲染的内容并没有减少,用户需要等待的时间还是那么多,对于长列表页面,用户第一次仅需看到上面的首屏内容,下面需要滑动才能看到的内容是没有必要一次性渲染给用户的。

这节课我们就学习使用虚拟DOM,以此来优化长列表内容的一个显示。


关于虚拟DOM的组件实现有很多,官方文档上的recycle-view组件就是其中之一,这个组件它特别适用于长列表内容的一个渲染,它在渲染的时候仅会渲染用户当前在这个视图里面应该看到的内容,对于看不到的内容则不会渲染,使用这个组件不仅可以加速首屏渲染的一个速度,还可以让运行时的列表滑动浏览更加的流畅。

接下来我们首先先看一下recycle-view组件它是怎么实现的?它实现的原理是怎么样的?


recycle-view组件是基于小程序的标准组件scroll-view组件去实现的,它是一个自定义组件,它的实现原理也很简单,一共包含两个部分:一个是recycle-view,一个是recycle-item

首先我们在渲染的时候需要知道每个循环单元的一个高度,这是消费代码需要传递给组件的。有了这个高度再配上屏幕的一个窗口高度,长列表组件以此就可以算出完整渲染整个列表最少需要的子组件,也就是recycle-item的个数了。当用户在这个屏幕上下滑动这个列表的时候,实际上子组件实例它并没有改变,页面上永远是那些子组件,就是那一组子组件实例在负责渲染,改变只是传递给它们的一个数据。换言之,在recycle-view组件里面,用户滑动的是数据而不是组件本身

现在我们在屏幕上看到一个示意图,这个图就是recycle-view组件运行时的一个示意图,至于滚动的高度是通过设置列表父组件的一个top属性,动态给它撑起来的。在列表滑动的时候使用子组件recycle-item循环渲染出来这个内容,相当于在一个长列表上的滑动,并且是可视范围一直是对准用户的视图窗口的这样的一种方式去渲染的。因为静态资源加载也需要时间,为了避免出现白屏,recycle-view组件会多渲染出前后屏幕、前后两屏的一个内容。它并不会只渲染当前我们这个屏幕看到的那些recycle-item,它会多渲染出两个屏幕的一些内容,以防备上下滑动的时候会出现一些白屏的地方看不到列表。


下面开始看实例演示。如何使用recycle-view组件?

recycle-view组件它并不属于标准组件的一部分,在使用之前我们应该像使用第三方的类库一样,使用npm或者是yarn指令对其进行模块的依赖安装。现在我们在屏幕上看到的这就是两个指令:yarn和npm安装指令,这两个使用任何一个都可以。原来微信开发者工具还需要在这个项目设置里面选择启用npm,现在已经不需要了。现在甚至连这个项目目录下的webpack.json文件,也不需要使用这个初始化指令。也就是我们现在屏幕上看到的这两个指令yarn init -y或npm init -y这两个指令也不需要使用这两个初始化指令的任何一个手动去创建了。

当我们执行安装指令的时候,它模块安装的同时webpack.json这个文件也会自动被创建,安装以后选择菜单工具→构建npm这一步不能省略。为了减少打包的体积,小程序会把最少量的模块代码从node_modules目录下面拷贝到miniprogram_npm目录下面去,这个目录才是模块加载时真正查找以及用到的一个目录。

模块安装以后,接下来我们需要在使用recycle-view组件的页面配置文件里面,也就是json配置文件里面去添加一个配置。像我们现在屏幕上展示的配置,把这两个组件就是recycle-view以及recycle-item这两个组件引用都需要添加到usingComponents节点下面去,添加完成以后,我们就可以在wxml这个页面里面使用我们的recycle-view和子组件recycle-item了。我们现在在屏幕上看到的就是一个示例代码,外围是一个recycle-view。

它有一个batch,batch等于batchSetRecycleData这个字段是不可或缺并且是不能改变的,相当于是写死的一个字段。每次使用的时候直接给它写成这个字段就可以了,往下是一个id等于recycleId,这是一个id,这个id是我们在JS代码里面会用到,然后组件里面我们还绑定了一个滚动事件,catchscroll它等于onScroll,它这个列表在滚动的时候会触发这个事件回调函数,在里边有两个slot,前后各有一个,一个是before,下面是after。然后再往里面是一个recycle-item,这个recycle-item是我们这个列表里面一个单元,在这个上面我们绑定了wx:for,这个是列表的一个渲染语法。这个里面用到的变量名称recycleList基本上也是写死的,稍后我们在JS代码里面可以看到。

然后这个地方我们还绑定了一个type事件onTypeRecycleItem,它是在我们单击这个列表元素的时候会触发的一个回调事件,然后这个上面还有一个是dataItem以及dataId,这是我们自定义dataset数据属性,稍后在代码里面会用到它。这就是我们的在wxml里面的使用的一个代码了,recycleList在当前这个页面里面就我们刚才在那个代码里面看到的变量,它目前是不存在的,它是由recycle-view组件在其内部就是组件内部动态将我们当前的页面的data数据对象上动态去设置的。这样设计方便我们在使用这个组件的时候自定义子组件的一个监听事件,因为我们可以看到我们在使用这个组件的时候,子组件就是我们recycle-item里面的这些wxml这些节点完全是我们自己定义的,我们可以加自己的一些逻辑代码、业务代码,这方便我们控制子组件的一个渲染样式。

下面我们在屏幕上看到的是我们JS代码,主要的一个JS代码这个里面我们里面首先是引用,要有一个对组件里面有个createRecycleContext一个引用,引用以后这是一个方法,稍后我们会调用它。然后再往下是一个ctx,ctx是我们用到的一个上下文对象,这个对象也很重要。再往下就是有一个dealWithListData这样的一个函数,这个函数是我们专门去处理,我们拿到的后端的这些数据,需要将这个数据在我们的长列表组件上然后进行设置和渲染。

我们组件还用到一些wxss样式代码,这些代码就像我们在屏幕上看到的这些一样,很简单。这是两个组件样式一个是控制了它的背景颜色,另外是它的一个padding 一个外边距,一个内边距。稍后完成以后,渲染的最终的一个效果就是像我们现在在屏幕上看到的一样,是这样的一种效果。


在改造旧页面的时候,我们可能会遇到这样一个问题:列表它会浮在原来的内容的上面,我们新添加的recycle-view这个页面附在原来的内容上面,像原来的顶部的banner以及导航内容遮挡住,这是由于wxss样式造成的,怎么解决?

我们看一下屏幕上的这两个样式,我们只需要将两个类样式里面的position样式给它去掉,原来它是指定了它的一个绝对定位,我们只要把绝对定位的样式给它去掉,这个效果就可以正常渲染了。

最后一次编辑于  2022-07-13
赞 9
收藏

6 个评论

  • HoMeTown
    HoMeTown
    2022-07-29

    真难用这个组件


    2022-07-29
    赞同 4
    回复
  • 少年锦时
    少年锦时
    2022-12-15

    不能实时计算每个节点的高度?

    2022-12-15
    赞同 1
    回复
  • YOhoho
    YOhoho
    2022-07-23

    不定高度呢?

    2022-07-23
    赞同 1
    回复 3
    • LIYI
      LIYI
      2022-07-30
      可以先基于一个默认的尺寸(例如iPhone 6s)做设计,因为上下有两个屏多余的渲染,所以也不会出现空白“缝隙”。在页面加载完成(Page.onReady)后,可以再基于真实的屏幕高度重新渲染长列表组件,
      2022-07-30
      1
      回复
    • 彡( ̄_ ̄;)彡
      彡( ̄_ ̄;)彡
      发表于移动端
      2022-11-05回复LIYI
      如果是不定高度item呢
      2022-11-05
      回复
    • Lewis
      Lewis
      2023-05-05
      瀑布流呢,左右两列,高度也不固定
      2023-05-05
      回复
  • 温水煮青蛙
    温水煮青蛙
    2022-06-27

    怎么获取视频源码?


    2022-06-27
    赞同 1
    回复 1
  • 清蒸鱼
    清蒸鱼
    2022-10-11

    目前开发用到的,只有图文的长列表似乎不会出现性能问题,没用虚拟DOM也很流畅

    2022-10-11
    赞同
    回复 2
    • 近未来
      近未来
      2023-02-10
      老哥你的图片压缩过吗,我的卡成屎了,我没压缩图片。
      2023-02-10
      回复
    • 清蒸鱼
      清蒸鱼
      2023-02-13回复近未来
      列表显示的肯定是缩略图,单独点开才是原图。如果不是前端上传的图片,那后端也要做好缩略图
      2023-02-13
      回复
  • Wᴀɪᴛ
    Wᴀɪᴛ
    2022-05-11

    视频不见了

    2022-05-11
    赞同
    回复
登录 后发表内容

小程序性能优化实践

课程标签