《小程序wx:for在更改数据后无法渲染页面》

背景

为扩展业务,提高搜索效率,增加tab筛选:[综合,销量,价格]

问题发现

点击tab,重新发送接口请求,列表数据更改之后,但是页面并没有重新渲染

问题分析

<block wx:for="{{ searchData }}" wx:key="index">
      <card-item messageChannelKey="{{ messageChannelKey }}" messageValPickKey="{{ index }}" cardType="normal" extraReportData="{{ extraReportData }}" />
</block>

点击事件触发,searchData已发生改变,但由组件<card-item />组成的feed流并没有发生渲染变化,根据上述代码,使用wx:for列表渲染,绑定的key值为index;组件<card-item />在attached时,进行卡片渲染。接下来,我们分别了解下,wx:for;wx:key;attached

wx:for

在组件上使用 wx:for 控制属性绑定一个数组,即可使用数组中各项的数据重复渲染该组件。

默认数组的当前项的下标变量名默认为 index,数组当前项的变量名默认为 item;

使用 wx:for-item 可以指定数组当前元素的变量名;

使用 wx:for-index 可以指定数组当前下标的变量名;

wx:key

如果列表中项目的位置会动态改变或者有新的项目添加到列表中,并且希望列表中的项目保持自己的特征和状态,需要使用 wx:key 来指定列表中项目的唯一的标识符。

wx:key 的值以两种形式提供

  1. 字符串,代表在 for 循环的 array 中 item 的某个 property,该 property 的值需要是列表中唯一的字符串或数字,且不能动态改变。
  2. 保留关键字 *this 代表在 for 循环中的 item 本身,这种表示需要 item 本身是一个唯一的字符串或者数字,如:

当数据改变触发渲染层重新渲染的时候,会校正带有 key 的组件,框架会确保他们被重新排序,而不是重新创建,以确保使组件保持自身的状态,并且提高列表渲染时的效率。

如不提供 wx:key,会报一个 warning, 如果明确知道该列表是静态,或者不必关注其顺序,可以选择忽略。

attached

组件重要的生命周期之一,在组件完全初始化完毕、进入页面节点树后, attached 生命周期被触发。此时, this.data 已被初始化为组件的当前值。这个生命周期很有用,绝大多数初始化工作可以在这个时机进行。组件不离开页面节点树的话,此生命周期不会再触发

此时,我们应该意识到,目前的场景是当点击tab时,当前的组件并没有离开页面节点树,而是需要对比新旧数据,进行重新渲染,这就涉及到wx:for和wx:index的相关内容,循环的searchData已发生变更,那感知当前节点变化是通过wx:key找到对应的旧虚拟DOM上发生改变的节点,由此,wx:key便是症结所在

问题定位

根据diff算法通过key对DOM节点进行唯一的绑定,给每一个vnode一个唯一的标识。

由于目前绑定的wx:key是index,那当切换tab时,虽然循环的searchData发生了改变,但是index都是从0开始,依次递增,继而重新给定key值即可

    <block wx:for="{{ searchData }}" wx:key="id">
      <card-item messageChannelKey="{{ messageChannelKey }}" messageValPickKey="{{ index }}" cardType="normal" extraReportData="{{ extraReportData }}" />
    </block>

后续

万变不离其宗,还得了解各个框架的核心优化点和改进点,深入原理,从根本上找到问题,思考解决方案,不至于有很多临时性解决方案,增加代码的坏味道。

1、React探索-diff算法 - 知乎

2、vue3.0 diff算法详解(超详细)_zl_Alien的博客-CSDN博客_vue3diff算法

3、聊一聊Diff算法(React、Vue2.x、Vue3.x) - 知乎

4、②Vue3 性能比Vue2好的原因(diff算法优化、静态提升、事件侦听器缓存)_只爭朝夕不負韶華的博客-CSDN博客_vue3的diff

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
如果不想使用`wx:for`指令来动态插入`<view>`,可以使用`<template>`标签的`is`属性来实现。具体步骤如下: 1. 在组件的wxml文件中定义一个`<template>`标签,并设置`is`属性为一个变量名。 2. 定义一个变量,用于存储要动态插入的`<view>`的数量。 3. 在组件的js文件中修改变量的,以控制动态插入`<view>`的数量。 4. 在组件的wxml文件中使用`wx:if`指令根据变量的动态渲染`<template>`。 以下是一个示例代码: ```html <template name="dynamicView"> <template is="{{viewList}}"> <view class="dynamic-view"></view> </template> </template> ``` ```javascript Component({ data: { viewList: null, // 初始为null viewCount: 2 // 初始为2 }, methods: { addView() { const viewList = [] for (let i = 0; i < this.data.viewCount; i++) { viewList.push(i) } this.setData({ viewList }) } } }) ``` 在上述代码中,我们定义了一个名为`dynamicView`的组件,使用了`<template>`标签的`is`属性来动态插入`<view>`。在组件的js文件中,我们定义了一个`addView`方法,用于根据`viewCount`变量的来生成一个数组,数组中的元素不影响渲染结果,只是用于控制`<template>`的渲染次数。在`dynamicView`组件中使用`wx:if`指令根据`viewList`数组的来动态渲染`<template>`,实现动态插入`<view>`的效果。调用`addView`方法后,`viewList`数组的长度会变为`viewCount`的,从而在组件中动态插入对应数量的`<view>`。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值