微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

列表渲染wx:key的作用以及条件渲染 wx:if 与 hidden之间的区别

本篇文章给大家带来的内容是关于微信小程序中使用async/await语法的方法代码示例),有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。

开发微信小程序离不开“页面渲染”,对于初学者来说很难理解小程序里的“页面渲染”是什么、怎么用?
而学过 vue 的同学来说,这个就比较熟悉了,实际上就是数据绑定页面渲染。
那么关于页面渲染最重要的是列表渲染和条件渲染这两块,先来看看几个简单的例子。

下面是个“列表渲染”的例子:

<view wx:for={{array}}>
  {{index}}: {{item.message}}
</view>
Page({
  data: {
    array: [{
      message: 'foo',
    }, {
      message: 'bar'
    }]
  }
})

上面的例子可以看出,认数组的当前项的下标变量名认为 index,数组当前项的变量名认为 item。当然,使用 wx:for-item 可以指定数组当前元素的变量名,使用 wx:for-index 可以指定数组当前下标的变量名,如下:

<view wx:for={{array}} wx:for-index=idx wx:for-item=itemName>
  {{idx}}: {{itemName.message}}
</view>

下面是个“条件渲染”的例子:

<view wx:if={{condition}}>True</view>
Page({
  data: {
    condition: true
  }
})

上面的例子说明,当 condition 为真时,页面渲染上面的 view 标签。当然也可以用 wx:elif 和 wx:else 来添加一个 else 块,如下:

<view wx:if={{length > 5}}>1</view>
<view wx:elif={{length > 2}}>2</view>
<view wx:else>3</view>

下面接入正题,探索文章题目的疑问

一、 列表渲染中的 wx:key 有什么作用

其实初次看 官方文档 可能会对 wx:key 有点懵,官方解释是这样的:

776779079-5c47d666d22d5_articlex.png

根据我多年看文档经验,一般我看不懂的可以忽略不重要的文字,只需关注重点,例如上图的文字加粗部分,因此,一开始我选择不写 wx:key 这个属性。然而在开发过程中写多了列表渲染(而没有加 wx:key)之后,控制台会报很多的 wx:key 的警告,对于有点代码洁癖的我看起来很不爽,但又苦于不清楚 wx:key 的真正作用,于是自创了一个解决办法,那就是在每个列表渲染后面加上 wx:key={{index}},类似下面这样:

<view wx:for={{array}} wx:key={{index}}>
  {{item}}
</view>

于是我惊奇地发现警告统统不见了,也没有其他负面影响,于是我就这样用了大半年。
然而,半年前我做的一个项目里面有个列表渲染需要试试获取用户头像和昵称,于是我之前的做法不管用了,每次获取到的用户信息跟当前内容不对应,并且会发生错乱。于是我重新理解了一遍 wx:key,结合下面的例子,我似乎明白了:

<switch wx:for={{objectArray}} wx:key=unique style=display: block;>
  {{item.id}}
</switch>
Page({
  data: {
    objectArray: [
      {id: 5, unique: 'unique_5'},
      {id: 4, unique: 'unique_4'},
      {id: 3, unique: 'unique_3'},
      {id: 2, unique: 'unique_2'},
      {id: 1, unique: 'unique_1'},
      {id: 0, unique: 'unique_0'},
    ]
  }
})

其实,wx:key 是用来绑定当前列表中的项目特征的,也就是说,如果列表是动态更新的,那么 wx:key 的作用是保持原有项目的整个状态不变。
结合上面的例子,我们可以知道,对于列表数组是个对象数组,那么 wx:key 属性直接写对应的唯一的属性名就可以了,比如上面的 wx:key=unique, 或者 wx:key=id 也是可以的,只要保持属性是唯一值就行了,有点类似页面标签里面的 id 属性页面是唯一的。
对于列表数组是个基本类型数组,那么直接写 wx:key=*this 就可以了,如下:

<block wx:for={{[1, 2, 3]}} wx:key=*this>
  <view>{{index}}:</view>
  <view>{{item}}</view>
</block>

巧用 wx:key 属性

  • 如果很明确自己的列表渲染是个静态列表,那么你可以像我一开始那样做,加个 wx:key={{index}} 就可以了

  • 反之,如果是个动态列表,那么就得在数组里找到唯一的键值,放在 wx:key 里面

  • 当然如果你无视警告,也不影响功能,不加也行

二、 wx:if 和 hidden 有什么区别

其实我们用条件渲染更多地在用 wx:if 而不是 hidden,因为前者可以拓展,后者缺乏一定的逻辑。然而他们到底有什么区别呢?
官方文档 是这样描述的:

1030953837-5c48181515780_articlex.png

上图中,我们大概可以了解到,如果需要频繁切换状态,用 hidden,否则用 wx:if。
也就是说,wx:if 能够实时创建渲染组件或销毁组件,而且当他为真时才会创建,初始为假时什么也不做,由真变为假时则进行销毁。所以频繁切换他是一个比较耗性能举动。而 hidden 则代表页面初始渲染时就会把该组件渲染在页面上,值的真假只是控制其显示隐藏罢了。页面不销毁,则该组件也不会被销毁。
明白了这一点,你会发现,从我们开发者的角度来说,灵活使用这两个条件判断会事半功倍。
下面列举几种使用场景给开发者参考:

<view class=load-event hidden={{!isAdd}}>加载中……</view>
<view class=load-event hidden={{!isAdded && isMore}}>没有更多了</view>

上面代码一个上拉加载动画显示与隐藏组件,可以看到用的是 hidden,因为他是一个需要频繁切换的组件。

<block wx:if={{node.name === 'p'}}>
  <view class={{node.attrs.class}} data-index={{index}} bindtap=toText>
    <text selectable=true>{{node.children[0].text}}</text>
  </view>
</block>
<block wx:if={{node.name === 'img'}}>
  <image class={{node.attrs.class}} src={{node.attrs.src}}></image>
</block>
<block wx:if={{node.name === 'video'}}>
  <video class={{node.attrs.class}} src={{node.attrs.src}}></video>
</block>

上面代码展示的是渲染文字还是图片或者是视频,只展示其中的一个那么用 wx:if 最佳。

下面是一个自定义 input 组件:

<view wx:if={{isInput}} class=show-input>
  <view class=input-item>
    <input class=item-input bindconfirm=onSend bindinput=inputHandle bindblur=hideInput></input>
    <view class=send-btn catchtap=onSend>发送</view>
  </view>
</view>

功能是点击评论按钮能实时显示输入框,否则隐藏。这里为什么用 wx:if 呢?因为我希望它显示时是新的 input 组件,不是之前渲染好的,这样如果我刚输入完文字,再次评论不会出现上一次的文字残留。

巧用 wx:if 和 hidden

  • 有时我们需要提前渲染好里面的子组件,那么要用 hidden,否则待显示时需要加上渲染的时间

  • 通常情况下,我在隐藏的时候都不需要该组件的话,那就用 wx:if

  • 如果需要在页面中点击切换的渲染,那么考虑小程序性能问题,还是用 hidden 为好

三、思考(引伸)

1、 <block> 这个元素在列表和条件渲染上是很好用的,不过要注意不要在这标签上绑定其他属性,比如 data- 或者绑定事件 bindtap。下面是一个反例:

<block wx:if={{true}} data-id=1 bindtap=tapName>
  <view>view1</view>
  <view>view2</view>
</block>

上面的代码里,在 js 中定义绑定事件后,你会发现不会执行。原因就在 <block> 元素在渲染页面后并不会存在,他不是个组件,不会渲染在页面树节点里面,所以在他上面绑定的事件或者属性也不会有效。

2、 当 wx:for 的值为字符串时,会将字符串解析成字符串数组;另外,花括号和引号之间如果有空格,将最终被解析成为字符串,请看下面的例子:

<view wx:for=array>
  {{item}}
</view>

等同于

<view wx:for={{['a','r','r','a','y']}}>
  {{item}}
</view>
<view wx:for={{[1,2,3]}} >
  {{item}}
</view>

等同于

<view wx:for={{[1,2,3] + ' '}}>
  {{item}}
</view>

本文参考:微信小程序开发基础教程 https://www.html.cn/study/20.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。