微信小程序 循环中 wx:key 的问题 微信小程序

shuke 2018-3-26 2506

A:数据改变,导致重新渲染的两种情况:


1:有wx:key的情况(不重新创建,仅改变顺序)

添加元素或改变元素顺序导致数据改变时,
会校正带有Key的组件(可通过key识别各组件),
框架会根据“目前数据”,重新排序各组件,而不是重新创建,
使组件保持自身的状态,列表渲染效率高。



2:无wx:key的情况(重新创建)

添加元素或改变元素顺序导致数据改变时,
此时各组件没有key(无法识别各组件)
框架会被迫根据“目前数据”重新创建各组件,
使组件重置初始状态(原有状态自然被清空),列表渲染效率低。



B:两种情况的对比

wk:key组件识别渲染情况状态情况for效率
各组件可识别渲染时仅改变组件顺序保持组件之前原来状态效率高
组件无法识别渲染时重新创建各组件重置组件的初始状态效率低

C:什么时候需要wx:key

1.需要wx:key的情况

  1. 列表中项目的位置会动态改变或者有新的项目添加到列表中
  2. 希望列表中的项目保持自己的特征和状态
    (如 <input/> 中的输入内容,<switch/> 的选中状态)

需要使用 wx:key 来指定列表中项目的唯一的标识符。

2.可不需要wx:key的情况

如果明确知道该列表是静态,或者不必关注其顺序,可以不用加wx:key,忽略如下的警告。

不提供 wx:key的警告: 


D:wx:key的使用及wx:key的值

1:wx:key="字符串"

这个”字符串”代表在 for 循环的 array 中 item 的某个“属性”
该“属性” 的值需要是列表中唯一的字符串或数字,且不能动态改变。
用于被遍历的组件需要多个属性的时候。

    //test.js      data: {        input_data: [          { id: 1, unique: "unique1" },          { id: 2, unique: "unique2" },          { id: 3, unique: "unique3" },          { id: 4, unique: "unique4" },        ]      }    //test.wxml    <input value="id:{{item.id}}"   wx:for="{{input_data}}"  wx:key="unique"  />

2:wx:key="*this"

保留关键字”*this”代表在 for 循环中的 item 本身,
这种表示需要 item 本身是一个唯一的字符串或者数字
用于组件仅需要一个属性,且属性值唯一。

//test.js  data: {    numberArray: [1, 2, 3, 4],    stringArray:['aaa','ccc','fff','good']  }//test.wxml   <input value="id:{{ item }}"   wx:for="{{numberArray}}"  wx:key="*this"  />   <input value="id:{{ item }}"   wx:for="{{stringArray}}"  wx:key="*this"  />  },

E:2个动态图的源码

//test.wxml<view class="container log-list"><!--有wx:key--><input value="id:{{item.id}}"   wx:for="{{input_data}}"   wx:key="unique" /><button bindtap="addToFront">    前部插入元素</button><button bindtap="switch">    随机排序</button></view>
//test.jsPage({  data: {    input_data: [      { id: 1, unique: "unique1" },      { id: 2, unique: "unique2" },    ]   },  //前部插入元素函数  addToFront: function (e) {    const length = this.data.input_data.length + 1;    this.data.input_data = [{ id: length, unique: 'unique_' + length }].concat(this.data.input_data)    this.setData({      input_data: this.data.input_data    })  },  //随机排序函数  switch: function (e) {    const length = this.data.input_data.length    for (let i = 0; i < length; ++i) {      const x = Math.floor(Math.random() * length)      const y = Math.floor(Math.random() * length)      const temp = this.data.input_data[x]      this.data.input_data[x] = this.data.input_data[y]      this.data.input_data[y] = temp    }    this.setData({      input_data: this.data.input_data    })  }})
//test.wxss.log-list {  display: flex;  flex-direction: column;  padding: 40rpx;}input {    background: none repeat scroll 0 0 #FFEEEE;     float: left;     width: 240px;    padding: 0 3px;    padding-left:10px;    height: 42px;    color: #69737d;    font-size: 16px;    line-height: 42px;    border: 1px solid #E70047;    margin: 20rpx;}button{  display: inline-block;   vertical-align: baseline; margin: 0 2px; margin-top:30rpx;outline: none;  text-align: center; text-decoration: none; font: 14px/100% Arial, Helvetica, sans-serif; padding: .5em 2em .55em; text-shadow: 0 1px 1px rgba(0,0,0,.3); border-radius: .5em; box-shadow: 0 1px 2px rgba(0,0,0,.2); }


最新回复 (1)
全部楼主
  • shuke 2018-3-26
    2

    让我们先看看代码

    .wxml 代码

    <block wx:for="{{items}}">
      <label><checkbox />{{item.title}}</label>
    </block>
    <button bindtap="chng">变更项</button>

    .js 代码

      data: {
        items: [
    {
      id: 1,
      title: "a"
    },
    {
      id: 2,
      title: "b",
    },
    {
      id: 3,
      title: "c",
    }
    ]
    },
      chng: function(e){
        this.setData({
          items: [
    {
      id: 2,
      title: "b"
    },
    {
      id: 1,
      title: "a",
    },
    {
      id: 3,
      title: "c",
    }
    ]
      })
    }

    效果如下:

    点击按钮“变更项”前,我们选中第二项,即 b 那一项。效果如下:

    wx:for 循环

    点击按钮“变更项”后,我们改变了 items 项的顺序。效果如下:

    wx:for 循环

    虽然字母顺序变了,但是选择项没有变。

    如果我们希望用户输入也跟随,则使用 wx:key

    wx:key 指定 items 中一个具有唯一值的属性,比如我们这里的 id,

    将 <block wx:for="{{items}}"> 改为 <block wx:for="{{items}}" wx:key="id">,注意:是 wx:key="id",不是 wx:key="{{id}}"。

    此时,点击按钮“变更项”后,我们改变了 items 项的顺序。效果如下:

    wx:for 循环

    以上只是改变顺序,如果是改变 items 元素个数,道理一样的。

    再细化一下,如果我们对 checkbox 使用了 checked="{{checked}}",而 setData 赋新值时为数组元素设置了:{ id:2, checked:false, title:"b" }, 而在点按钮之前又选中了 b,点按钮后,是继续选中 b,还是听新值的呢?听新值的。

    那新值不要 checked 属性,是不是就继续选中 b 呢?也不是,因为没有赋值,对 {{checked}} 来说,相当于 false(boolean 默认值是 false)。


返回