收藏
评论

视图代码优化技巧官方


你好,我是李艺。

上节课我们主要介绍了微信开发者工具中一些调试工具的使用,这节课学习视图代码的优化技巧。

首先看一下问题,微信开发者工具里面的性能优化工具中,有一个非常重要的性能优化工具,也就是体验评分,我们还没有介绍,从调试区单击体验评分面板,也就是Audits面板,就可以看到微信开发者工具,对当前小程序项目的运行评判结果了。在这个面板里面会给出很多具体的优化建议,下面从8.1到8.7讲,我们会重点介绍体验评分面板里面所提到的优化事项,以及相关的优化技巧。下面看项目实践。


首先看实践一,在动态列表渲染里边优化wx:key的使用。

先看一张示意图,如我们现在屏幕上展示的这一张,假如有一个数据列表,它的起始数据内容是ABC,后来数据发生变化了,变成了AHBC,那么当这个列表数据变化的时候,它们在这个视图里面的列表渲染会引起什么样的一个变化,在小程序里面wx:for这个标签属性它用于列表渲染,wx:key用于指定列表渲染里边列表项的身份标识,如果这个列表中,它每一项都有一个唯一的key,当有一项新数据增加的时候,例如我们这个列表里面增加了一个H,在重渲染的时候,小程序它会创建一个新节点,并且把这个数据H更新给它,同时将这个BC节点在这个列表中向后移动,如果这个列表里边它每一项没有一个有效的key,小程序它就无法正确识别这个视图里边列表元素与这个列表项的一个对应关系,这个时候小程序同样会创建一个新节点,但是会依次将HBC更新给这三个列表项,与前面那种更新方式相比,也就是与有唯一wx:key更新的方式相比,后面这种更新方式小程序会重新渲染三个节点,而前面那种方式它只需要渲染一个节点,从这个列表数据的这个重渲染机制来看,对于列表数据的动态渲染,使用wx:key属性,并且给每一个列表项设置一个唯一的key是十分有必要的,具体怎么做呢?

在我们的这个页面标签代码里面如我们屏幕上看到的,我们可以将这个wx:key给它指定一个字段id,这个id它是唯一的,在主页的wxml文件里面,一共有三处使用了wx:key属性,在使用wx:key属性时,它的取值情况我们大致可以分为以下两种。第一,如果列表元素是单一的基本数据类型,并且是唯一的,这时候我们可以直接写成*this,这里这个*this,就代表当前数据列表里面的数据元素,如果列表元素它是一个对象,也就是Object的类型,我们可以填写成列表元素对象里面的一个字段名,这个字段要在这个数据列表里边是唯一的。如果这个列表它不是动态的,只渲染一次,wx:key设置与不设置,这个时候是没有差别的,此时wx:key属性可以设置为index,index是一个默认的下标变量名,这种设置虽然没有实际效果,但是却可以有效消除,微信开发者工具,在调试区所呈现的黄色警告,首先我们打开我们的主包index下面index.wxml文件,在这个文件我们有多处使用了wx:key这个标签属性,我们可以检索一下。检索一下上面的所有的用到的标签属性的地方,第一个,这是我们的滑块视图区,在这个里边我们用了一个wx:key这样的一个标签属性,它的这个值目前是*this,这种写法前面我们提到了也是可以的,但是对于我们目前的swipers列表数据,因为它是静态的,所以这个地方我们没有必要这样去写,这个地方我们直接写成index就可以了,接着我们再往下查看下面的使用这个标签的地方,这个地方是一个长列表内容区,这就是长列表内容区了,这地方我们用了这个recycle-item,在这个地方有一个wx:key绑定。注意这个列表它已经是一个动态数据列表了,然后我们从后台会不断拉取新的数据,然后填充进来,所以这个地方我们用index就不太合适了,我们可以用它这个数据列表里面,它本身所含有的,所包含的字段,比如说id,id就是它里面的一个唯一的字段,所以我们这个地方可以用id作为它的一个字段名,这样就可以了。

我们再看其他的,这两个地方都已经改了,另外我们还要看一下我们导航区在这个地方,这个地方我们也有一个wx:for列表渲染,我们这个页面里面一共有三个。这个地方也有,但是它目前还没有这个wx:key属性,导航区的列表,它是一个静态列表,它其实并不是动态的,所以我们这个地方简单起见,也可以使用index,给它写一个index就可以了,写完以后在我们调试区就不会出现一个黄色警告了,不然的话它会有一个警告提示,会让我们给它加一个这样的wx:key,加这样的一个标签属性,这个代码演示就到这里。


下面我们看实践二,绑定视图事件。

使用catch,代替bind,减少dataset的一个数据运输量,在很多教程示例里面,绑定事件,一般默认使用的是bind,但是大多数情况下,我们监听的事件,它其实并不需要冒泡。我们只是需要在某个特定的wxml节点上监听事件,这种情况下我们完全可以使用catch代替bind,使用catch绑定视图事件可以自动忽略冒泡阶段,避免因为不必要的事件触发,造成额外的逻辑层代码的一个执行的浪费,还有在添加事件监听属性的时候,一般我们需要回传一些额外的信息,这个信息可以使用以data-开头,这样的一种形式,去定义自定义属性,通过事件对象进行传递。但是在JS逻辑层,我们实际需要什么样的一个信息就传递什么信息就可以了,不要因为为了省事,将一个很大的数据对象整体传递过去,也不要传递多余的本来它就不需要的一些信息。例如在我们这个onTapRecycleItem,这个函数体代码里面,我们只需要传递进来一个index就可以了,在有了这个index索引数据以后,其他的一些信息像id,我们就可以直接从allList列表数据里面去获取,如我们现在屏幕上看到的代码截图所示,在主页JS文件onTapRecycleItem这个方法里面,id信息就是通过index索引间接取到的,每次事件回调函数的一个触发都涉及到一次,从视图层到逻辑层的数据传递,如果每次传递的数据量小于64KB,并且在30ms以内可以执行完成,这样的一种情况就属于一个正常操作,这种情况下一般都不会太影响页面的一个正常渲染。

在VSCode里面打开我们目前的代码,我们可以从这个项目的基本信息里面,然后确认我们本地代码它所在的位置,所在的一个本地目录的一个位置,这是我们当前代码的一个位置,然后在这个代码里面,在小程序的源码里面,我们进行一个全局的查找,比如说我们查找bindtap,查到它,查到以后我们可以看到,10个文件里面有14个结果,可以依次单击查看,这个地方有很多都是bindtap,刚才我们提到了大多数情况下,我们所有的关于tap这个事件监听,其实都不需要使用bind,我们使用catch就可以了,所以这个地方可以直接改成catch,可以改成它,改成它以后,我们然后单击全部替换,这样就可以了。改完以后我们可以在小程序这个项目里面,微信开发者工具里面,然后单击编译进行测试一下,看看有没有问题,一般情况下都是没有问题的,这是一个修改。其他的一些事件,其实我们还可以修改,查找,在我们这个里边有其他的一些绑定,事件绑定,所有以bind开头的其实都可以,这个地方我们还可以排除文件,也可以限制,可以排除js文件,还有json文件也可以排除。因为本质上我们需要查找的只有wxml文件,标签文件,当然这个查找它可能会查找出很多,查找以后 然后我们可以采用单个修改的方式,然后把它们给它替换了就可以了。

下面我们再看另外一个地方,就是在我们主页里边,我们有一个长内容列表,有这样的一个列表,这个列表里面在它列表项渲染的时候,我们传了通过data自定义数据属性传递了两个额外的信息,一个是id,一个是item,这两个信息传进来了,并且这个信息在在我们回调里面,在js里面我们是有使用的 我们可以看一眼,在这个地方,我们直接取了从dataset对象上取了id,item也取了,我们有取用,这个地方其实我们也可以修改,对于我们不需要的一些信息,我们没必要传递。并且这个信息量要尽量传的小一点,像item这个信息它其实是比较大的,因为它整体是一个Object的对象,整个对象的传递,它其实是非常浪费我们有限的设备资源的,这个地方我们传一个index,它其实当前列表里面索引,这两个就不需要,给它去掉,去掉以后,在我们js里面这个地方,我们就可以先取我们index相同的方法,把index这样取到,这个取到,然后下面这两个不能这样去取了 ,但是我们可以间接去取,因为我们这个地方这是用了两个对不对,我们可以间接来取,怎么样间接来取,怎么间接来取,看一下我们最终的源码。

第二个代码演示。

在这个地方先取到index,然后通过allList取到item,然后再从item上面取到的id,这样的话这两个信息都取到了,把这个代码我们拷贝 一下放在这里,然后allList我们可以看一下,它其实是在我们当前data数据对象底下,有这样的一个列表数据,而我们传进来的index其实是它的一个索引,在它里边的索引,我们的标签里面,我们知道我们这个地方,我们用了recycle, recycle-view组件,用了组件以后,我们内部的渲染的index,其实不是它的索引,是我们所有的allList,它本身所有数据的这样一个索引位置。所以在这个地方我们可以这样来使用,这个代码修改完以后,我们可以测试一下,然后单击刷新,单击某一项 ,没有输出,为啥没有输出,是我们没有触发吗,这个地方写错了,这是开始应该是catchtap,其实并不是catchbind,因为我们刚才替换的时候这地方是有问题的,刚才我们替换了14个,对不对。现在将这14个然后再重复再替换一下,这种替换我们要小心,刚才我们替换以后,其实我们也同样进行了单击测试,但是没有发现错误,像这种标签,绑定标签写错了,然后本身程序也不会发生错误,只有我们实际测试的时候,相关功能的时候,然后才会暴露出来,这个改完以后我们再单击编译进行二次测试,Ok。现在我们可以看到,我们单击哪一项,它现在所打印的列表项5,标题5,标题6,就是我们所单击的这一项,说明我们传递index的数据它本身是准确的,另外在我们打印代码,我们目前的这种方式,因为我们只传了index,相比我们原来的这种方式其实已经优化了一些了,这个代码演示就到这里。


下面我们看实践三,使用节流函数和防抖函数,防止按钮误点击与scroll事件函数频繁触发。

什么是节流,顾名思义就是控制某段JS代码的一个执行频率。举个例子,限制某类事件,一秒内只能触发一次函数执行或者是三秒发生一次,这样就是一个节流,在scroll input事件里面,如果触发网络请求或本地缓存读写这样的一个代码执行,由于此类事件它的派发比较频繁,所引发的操作又比较费时,这时候就很容易造成程序卡顿,这种场景便适合使用节流操作。下面我们再看一下什么是防抖,顾名思义就是防止抖动,避免把一次事件当做多次来处理,敲击键盘就是一个经常都会遇到的防抖操作场景,在这个网页里面我们监听用户单击键盘或者是某个按钮,为了防止用户误点了多次,这种场景下就适合使用函数防抖。什么时候应该节流,什么时候应该防抖,简单来说事件比所驱动的操作频率快,这种情况下我们用节流。事件与所驱动的操作频率都很快,这种情况下我们用防抖。在主页的JS代码里边,有两个防抖与节流的例子 我们一起来看一下,如我们现在屏幕上看到的截图所示,它所使用的throttle防抖函数,消弱的是列表项的单击回调函数的一个执行次数,对于这个onScroll,它使用的是debounce节流函数,消弱是列表的滚动事件,回调函数的一个执行次数,在测试项目的时候,我们从调试区可以清楚看到,防抖与节流的一个具体的打印信息,效果还是很明显的。

下面我们看代码实战。

在使用防抖和节流函数以前,首先我们需要实现这两个函数

我们看一下最终的一个源码,这个源码在8.1.3。我们找到在library下面 optimus下面

然后有一个throttle,另外还有一个debounce,这两个,一个是节流,一个是防抖。这两个我们把它拷贝一下,然后放在我们目前的项目下面,先拷贝过来,然后我们再看它的一个具体的实现,我们先看throttle,节流函数是这样的,我们要传进来一个method方法或者一个函数传进来,传进来以后,同时还要传进来一个,我们期待等待的一个时间,就是节流的时间,这个单位是ms,再下面我们会传进来以后,我们会返回一个闭包,其实它是一个匿名函数,是一个闭包,然后在每次我们这个闭包要执行的时候,我们首先要查一下,这个时间与我们前面的时间,它所相差的时间差,如果是大于我们设定的时间值,比如说50ms的话,我们就调用它,同时把前面的记录的时间值给它更新一下。否则的话我们就是打印一个节流少许这样的文本,然后就放弃执行了。这是主要的一个代码,接下来再看debounce它的一个执行,debounce也是要传进来一个方法,或者是函数传进来,然后还有一个时间wait的设置默认也是50ms,在这个地方我们要看一下,因为它触发执行,它可能是多次进来,所以我们也要返回,有这样的一个返回,返回以后,当返回的闭包被执行的时候,我们这里边会有一个setTimeout,就是设置一个延时定时器,当达到这个时间的时候,然后去调用它,然后去执行。因为它后面会可能有重复的事件触发时间点给它传进来,然后触发它的一个执行,所以这个地方,当后面的它进来的时候,我们要看一下它这个timer是不是为空的,如果它不为空,首先我们要清除,清除以后然后打印一个防抖少许,然后接着再去设置一个延时定时器,这样的一种方式,达到一种防抖的这样一种效果就是避免我们单击某一个按钮的时候,单击多次,然后执行多次的这样一种情况,因为用户他可能会出现误点的这种情况,我们需要将他多次单击然后处理成一次单击,然后这样去对待,这是我们两个方法。工具函数已经有了,接下来我们要再看怎么样去使用。

首先打开我们主页,在主页文件,使用之前,首先我们要引入代码,敲一下我们的引入代码,一个是debounce,然后是路径,library,optimus,然后是debounce.js,这是这一个。另外我们还有一个是throttle,这两个它的位置一样,其实只是它的名字不一样,以简单可以把它给拷贝过来,然后把这个名字给它改一下就可以了 ,下面我们开始应用,首先我们需要查看一下我们当前主页上,第一个我们先看一下我们最终的源码,看我们最终源码里边是怎么样去用的,打开首页,这是引入的先看throttle节流,这个地方,我们用到的onRecycleViewScrollToLower,就是我们滚动列表,它滚到底部的时候开始触发的,这样的一个事件回调函数,我们需要对它进行一个节流,进行节流。使用的方法就是我们直接在它后面这个方法,它这个方法的前面,然后给它加这样的一个throttle的调用,把它作为一个参数,它返回这个闭包,然后再给前面这个,这样的一种方式。我们先看一个使用。


在我们的代码里边,找到Recycle,也就这个方法,这是我们现在这个代码,然后我们要改写的话,只需要在它这个地方,加一个它,让它作为一个参数传给它,这样,这样就可以了,很简单。下面我们再看另外的一个使用,再看看还有没有其他的一个,还有onScroll,onScroll的时候我们也使用了throttle这个函数,所以这个地方我们还可以在它的下面这个地方,这个写法跟上面那个稍微有点不同对不对,但是我们可以改写,throttle然后传给它一个参数,然后这样传给它,然后这个地方加一个小括号,这样就可以了,这是关于throttle。然后另外还有debounce的使用我们来看一下,是用到了onTapRecycleItem这个方法上面,然后回到我们这个项目里面,先查找一下这个方法,在这个上面,用到它的上面,我们同样的一个方式,在它的后面加一个debounce,然后传给debounce的一个参数,一个匿名函数传递给它 作为它的一个参数,这个改写就完了。基本上就是我们在它原有的函数外面,然后多加一层 加一个方法的一个调用,代码写完了,然后我们单击编译做一个小的测试。

有问题了,有问题是正常的,然后我们看一下什么问题,现在我们看一下在我们的调试区,然后报出了异常,大概是在我们request.js这个位置,然后它触发了一个异常,我们可以在这个地方简单打一个断点看看它有什么样的一个,然后再刷新一下,此时这个参数是没问题的,可以把它放过去,因为对于同样一个方法的调用,它可能多个地方都调用到它了,并不一定每个地方都会发生问题,有可能只是某一个地方发生问题,这个时候我们可以看到我们args现在它是一个undefined,然后我们在undefined上面调它的url显然是有问题的,所以代码这个地方出现了问题,为什么这个参数会产生空的这样的一种情况呢,发生问题我们主要要往前梳理,看一下我们刚才主要修改了哪些代码。我们刚才在这个页面的首页,js文件这个顶部我们添加了两个函数,然后在这个地方引入的时候,我们这个地方关键字写错了,这两个长得很像 ,一个require 一个request,对不对,长得很像,我们给它改过来,都改成require,改完以后,然后我们再测试一下,现在这个问题就不再出现了。

我们接着测试,我们刚才新添加的防抖和节流这样的一个功能,对不对,首先是滚动,当我们往下滚动的时候,列表发生了滚动,这个代码是谁打印的,是我们里面的有一个叫做onScroll,是它,这个地方有一个列表发生滚动,是它打印的,但是我们这个地方为什么节流函数还没有添加,是我们前面加错了吗,我们检查一下我们,检查一下我们下面的方法,onScroll这个是有的,这里边有两个重复了,所以我们这个地方将这个给它拷贝一下,这种一般我们放在底部,因为它这里面页面函数如果你有重复的话,它会用你下面的,下面会把上面给它重写,然后你上面即使加了throttle,它也没有效果了,是这样的一种方式。并且这种错误也不容易发现,这个要靠我们细心,修改以后,然后我们再单击编译,再次测试,向下滚动,然后刚才我们看到的打印是列表发生了滚动,没有节流少许的一个打印对不对,现在我们再滚动的时候,我们可以发现它会有节流少许的一个打印信息,我们滚动得越快,打印信息越多,这样的一个方式,它减少的是对我们onScroll方法的一个调用,这是它,另外我们throttle,还有一个地方是在onRecycleViewScrollToLower事件回调上面,也加了throttle,这个是在我们滚动到底部的时候,它会发生,也就是在开始拉取新的数据之前,它会发生一个,然后这样的一个东西,我们会同样也是打印节流少许,因为节流少许它是在统一的throttle这个里边去打印的,打印数字是一样的,它跟我们滚动时候以及滚动到底部的时候打印的是一样的,这是两个。

接下来我们再看另外的一个防抖,防抖我们检索一下,debounce,在onTapRecycleItem,我们单击这个,然后它会出现这样的标题,当然我们刚才单击是比较温柔的一种单击。现在我们对它进行暴力单击,你看短时间内单击多次,然后这个时候我们防抖少许就已经有打印了,正常的单击一次其实是没问题的,一般情况下不会有问题,但是如果是我们单击多了,然后它这个地方就出现了,单击防抖少许,这是它的主要的一个作用。下面我们再看一下我们这两个工具函数的一个写法,基本上最简单的一个写法就是我们在用这样的一种方式,前面是名字,然后后面跟一个匿名函数,然后我们再把throttle或者是debounce,然后加在后面匿名函数的外面,然后对它重新包一层就可以了,这种情况下我们在这个里面如果是用了this的话,this它仍然不会丢失,它仍然会指向我们当前的页面,也就是它原来该是什么样子,现在还是什么样子,而不会受到影响,另外还有一种写法是什么写法。我们看一下,我们拿这个debounce来看一下,把function给它删掉,改成箭头函数,这样的一种方式,改完以后这是一个。另外我们还可以同时再改一下,我们的throttle,这个地方也可以给它改成,箭头函数的一种方式,然后下面还有一个这个,改完了,然后重新单击编译进行测试。首先是滚动没有问题,然后滚动到底部,滚动到底部的时候发生了问题,我们可以看一下,这个是我们在发生滚动到底部的时候,我们可以再测试一下,看到没有滚动到底部的时候,它其实是我们的,我们可以检索一下我们滚动到底部的函数,看一下,onRecycle在这个里边对不对,然后它提示我们不能访问空对象的this,也就是在这个地方它的this丢失了,它this丢失了,它是一个回调函数,这个地方this丢失了,所以在这个地方保守的一种方式,我们把它改回来,加上function这样一种方式,我们这个里面用this了看到没有,这个地方,这两个地方都用了this了,当我们改成箭头函数的时候,它其实不太好使,而用这种传统的写法,function这种匿名函数的写法,反而能够保留this它正确的一个指向,保留this正确的指向,然后我们再看另外一个地方。

这个地方倒不会出现问题 因为这个地方,我们即使对它改写成这样的一种,改写这样一种箭头函数的一种方式,因为它里面没有用this,所以它没有问题,所以这个地方无所谓,我们用,当然我们也可以改回来,如果是我们后续的代码里面,如果再增添代码,需要使用this对象的话,我们可能也需要给它改回来,这是一种方式。另外一个debounce,看一下debounce,debounce这个里面也用了this对不对,我们可以测试一下,这个是单击,把这个清一下,看到没有,它也会提示这样的一个错误,this没有找到解决方式的跟那个也是一样的,我们也可以加,把它改回来加上function,箭头函数给它去掉。这个地方有个问题我们思考一下,为什么我们把后面改成箭头函数的时候,它里面this为什么会丢失,为什么我们用function它不丢失,简单来讲就因为我们用箭头函数,因为箭头函数它本身,它是没有自己的,this对象的箭头函数是没有自己的一个this对象的,然后如果我们在箭头函数里面,然后用了this的话,它会取它上一个,就包含这个箭头函数的,所在的父函数里面的this对象,它这个父函数是谁,父函数是这个debounce或者throttle,而这个debounce和throttle我们知道其实,我们是在哪里定义的,我们是在我们另外的一个文件里面单独定义的。你像这样的一个文件,其实它是属于什么,它相当于是全局函数,你在这地方取this对象,取到的谁,取到的其实是全局对象。然后你在全局对象上再取它下面的data,你显然这种情况是取不到的,而另外一种方式写法,我们用function的写法,这种写法其实它就比较保险。它本身它作为一个就是最朴素的,经典的一种函数的写法,它本身是可以持有自己的this的,然后我们可以保留,我们原有代码里面的这种this对象的一个正确性,同时我们在throttle或debounce里面,我们也不需要将this给它传进来。因为我们在调用它的时候再把this对象传进来,反而增加了我们这个方法调用的一个复杂度,所以最简单的一种写法,就是我们在前面加上 外围加上一个debounce或者throttle,然后同时里面保持function的这样一种原始的写法,这样就可以了。这是我们在使用这两个工具函数的时候,我们需要注意的一点,不然的话可能会造成this对象丢失,给我们这个代码,给我们项目造成一些不易察觉的错误或者是异常。


下面我们看实践四,重渲染与使用wxml标签要克制。

前面我们曾经介绍过小程序有重渲染机制,这个机制在setData方法触发视图更新的时候会起作用,每次重渲染时小程序,将data与setData的一个新数据套用在wxml标签上,得到一个新节点树,然后将新节点树与当前这个节点树进行比较,这样就可以知道哪些节点以及哪些节点属性需要更新,还有知道哪些节点需要移除或者是添加,最后将setData新设置的数据合并到data数据对象上面去,并且使用新节点树替换原节点树,完成组件或者是页面的渲染工作。在重渲染过程中,我们可以看到有两个影响渲染效率的点,第一个点是wxml组件节点越多,嵌套的层次越深 越复杂,这时候渲染就越麻烦,渲染起来效率也会越慢。第二个就是我们通过setData传输的数据量,数据越多,渲染也就越慢,所以这个地方怎么优化就很明显了,一是减少wxml节点的数量,二是控制setData每次传递的数据量。需要更新哪些节点,我们只传这些节点需要的数据就可以了,有时候开发者他为了简单方便,他每次需要改变数据的时候,他先设一个data这样的临时对象,然后把需要更改的这些数据都写在了一个对象里面,最后再统一调用setData(data)这样的一种粗暴的方式,然后进行更新,这样的写法虽然简单,似乎还拥有一种暴力美学的一种美感,但是它的更新效率却是十分低下的。对于小程序页面的wxml节点,官方建议的优化标准是总页面节点树小于1000个,节点深度层级小于30层,子节点树不大于60个,在编写页面代码的时候,我们时刻应该保持一颗克制的心,要有初代程序员写代码时那种一个字节,一个字节去抠的一个细致精神,对于页面里边的节点,能用text标签就不要用view标签,能直接用文本就不要用text的标签,对于一些循环渲染的列表可以使用block标签的,我们就不要再浪费一层view标签。我们举个例子,对于stopwatch_nw组件,在它的wxml页面里边,我们可以看一下,如屏幕上展示的代码截图所示。在精简标签以后,只有这个slot插槽和这个text文本标签存在,而其他的子标签都不再需要了。

下面进行实践四的代码演示。

在我们的项目里面找到我们的秒表组件标签,我们以stopwatch_nw组件为例,看一下它这个标签代码,这是它这个标签代码,原始标签代码,对于这样的一个标签代码,其实我们是可以优化的。你比如像这个地方,它的slot插槽外面仍然有一个view标签,这个其实是可以去掉的 是不需要的,所以我们在这个地方可以怎么样修改,复制一份到下面把上面的给它注掉,然后这个地方view不需要了,去掉,然后这个text它本身其实也是可以作为一个节点,就是文本本身,它其实没有必要一定要放在一个text,或者是view这个节点下面,它本身也是可以存在的,所以这样写也是没有问题的,我们可以精简成这样一种状态。当然对于我们目前的组件,因为它标签不是特别复杂,我们这里只是演示怎么样尽量去减少页面以及组件的标签的节点的复杂度,以及嵌套的层级。尽量减少节点,尽量减少嵌套的层级,这样的话可以优化我们视图的一个渲染效率,关于这个代码演示我们就说到这里。

最后总结一下,关于视图代码优化的小技巧。第一点,使用wxml标签要克制,能不用容器标签就不用,能少用标签就少用标签。第二点,默认使用catch代替bind绑定事件,自定义的data数据属性里边永远只存储基本的数据类型,并且只存储小数据。第三点,在动态渲染的这个列表里边,一定要绑定一个唯一的wx:key,静态渲染的我们可以使用index。第四点,对于scroll高频事件,我们要节流 使用这个节流函数throttle。第五点,对于用户的单击事件,尤其是高频触发的一个单击事件,可以适当使用防抖函数debounce,视图代码主要就是wxml标签代码,优化视图代码,就是优化对wxml标签及其属性的一个使用,通过小程序的性能工具,我们可以发现启动过程中,有一个叫做Parse WXML的过程,如果页面足够复杂,标签嵌套足够深,那么Parse WXML的过程它的耗时就会很长,wxml和wxss它是经过解析后才能完成视图层代码注入的,如果这个过程很长的话,势必会影响冷启动的一个总时间。这节课我们就讲到这里,上面的网址是本课所涉及的文档地址。

点击查看开放文档:


这节课我们主要学习了关于视图标签及其属性的一些优化技巧,下节课我们学习wxss优化技巧。

最后我们看一下思考题,这里有个问题请你思考一下,小程序项目在开发过程中样式代码会改来改去,总是会产生一些废弃的但是又没有及时删除的一些样式代码,这些代码如果也打包在最终的代码包里面,势必会造成对昂贵的代码包额度的一种浪费,那么有什么办法可以快速地将不再使用的样式代码删除吗?下节课我们就一起来深入探讨一下这个问题。

最后一次编辑于  2022-07-15
赞 1
收藏

1 个评论

  • Reload
    Reload
    2022-09-09

    开始代码演示那块应该是bindtap改catchtap吧,怎么改成catchbind了?

    2022-09-09
    赞同
    回复 1
    • 清蒸鱼
      清蒸鱼
      2022-12-19
      你往下看他发现错误了
      2022-12-19
      回复
登录 后发表内容

小程序性能优化实践

课程标签