列表渲染 wx:key 的做用、条件渲染 wx:if 与 hidden 的区别

这是微信小程序踩坑系列的第三篇,想要了解更多关于微信小程序开发的那些事,欢迎关注个人《微信小程序》专栏。javascript


前言

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

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

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

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

<view wx:for="{{array}}" wx:for-index="idx" wx:for-item="itemName">
  {{idx}}: {{itemName.message}}
</view>
复制代码

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

<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>
复制代码

下面接入正题,探索文章题目的疑问微信小程序

1、 列表渲染中的 wx:key 有什么做用

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

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

<view wx:for="{{array}}" wx:key="{{index}}">
  {{item}}
</view>
复制代码

因而我惊奇地发现警告通通不见了,也没有其余负面影响,因而我就这样用了大半年。 然而,半年前我作的一个项目里面有个列表渲染须要试试获取用户头像和昵称,因而我以前的作法无论用了,每次获取到的用户信息跟当前内容不对应,而且会发生错乱。因而我从新理解了一遍 wx:key,结合下面的例子,我彷佛明白了:ide

<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 里面
  • 固然若是你无视警告,也不影响功能,不加也行

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

其实咱们用条件渲染更多地在用 wx:if 而不是 hidden,由于前者能够拓展,后者缺少必定的逻辑。然而他们到底有什么区别呢? 官方文档 是这样描述的:

上图中,咱们大概能够了解到,若是须要频繁切换状态,用 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 为好

3、思考(引申)

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

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

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

二、 当 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>
复制代码

4、参考连接

(完)

本文做者 Thinker

本文若有错误之处,请留言,我会及时更正

以为对您有帮助的话就点个赞收藏吧!

欢迎转载或分享,转载时请注明出处

阅读原文

相关文章
相关标签/搜索