收藏
回答

【框架】列表的wx:key设计的是不是有问题?

文档中关于wx:key的描述如下:

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

  1. 字符串,代表在 for 循环的 array 中 item 的某个 property,该 property 的值需要是列表中唯一的字符串或数字,且不能动态改变。

  2. 保留关键字 *this 代表在 for 循环中的 item 本身,这种表示需要 item 本身是一个唯一的字符串或者数字

——————————————————————————————————————————————————

之前没太注意这块,现在发现项目里很多地方都是这么写的:

<view wx:for="{{ list }}" wx:key="{{ item.id }}">......</view>

是想将表达式{{ item.id }}的返回值作为唯一值


我的问题是,这种写法对么?列表元素可以成功复用么?

根据文档1,“代表在 for 循环的 array 中 item 的某个 property”。实际上,有没有可能把表达式{{ item.id }}的返回值当成了property,然后key用的是item[ property ],也就是 item[ item.id ] ?或者有没有可能最后key用的是item["{{ item.id }}"]?那应该都是undefined,为啥我的示例里都没有报错呢?


提供一个示例,https://developers.weixin.qq.com/s/5s3XdomT7w8T


这绝对不是一个少见的问题,我看社区里很多人都这么用了

—————————————————————————————————————————————————

更新一下,加一个示例,这个示例的现象也不太正常:https://developers.weixin.qq.com/s/AytL4pmM7k8p

—————————————————————————————————————————————————

原来这个问题存在快1年了

  1. https://developers.weixin.qq.com/community/develop/doc/000c2074590aa08e98372150c5b000?highLine=wx%253Akey

    这篇文章的作者是严谨的,而回答全是瞎扯

  2. https://developers.weixin.qq.com/community/develop/doc/000a82ab2d07682a699788d585bc00?highLine=wx%253Akey

    这篇文章的作者遇到的现象是诡异的,而回答给他的解决方案,瞎扯

  3. https://developers.weixin.qq.com/community/develop/doc/00062ec7eecea8f64427829ab5b400

    这篇文章官方回答了,但是太言简意赅,导致底下的回答还是在瞎扯

  4. https://developers.weixin.qq.com/community/develop/doc/000ee2aca04a102195278397e51c04

    这篇文章,从头到位都是瞎扯


其实我上面的瞎扯都想用放屁来代替的,就这么个问题,磨磨唧唧弄了这么久,大部分人都还是在瞎搞。是当初设计的锅?还是文档没写清楚的锅?还是因为官方的不重视?还是社区质量太差?

即便严格按照文档的说法,我上面的两个示例还是解释不通的,哎。。。

最后一次编辑于  2019-05-16
回答关注问题邀请回答
收藏

5 个回答

  • 黄思程
    黄思程
    置顶回答2019-05-17

    wx:key 里有花括号是无效的写法,官方示例的错误写法我们梳理一下。 按照你上面的例子,正确写法是 wx:key="id"

    2019-05-17
    有用
    回复 3
    • 卢丑丑
      卢丑丑
      2019-05-19

      嗯的,正确的写法我知道的。我更想知道的是错误写法时候发生了什么。问两个问题:

      一、我提供的第二个示例,有效的wx:key会导致触发自定义组件的moved生命周期。无效的wx:key,自定义组件attached、ready、moved、detached生命周期都没有被触发,也就是说自定义组件还是被复用了?这里的逻辑是什么

      二、如果没有一个唯一的id,又不想在控制台看到报错,wx:key该怎么写?比如

      <view wx:for="{{[1, 1, 1, 1]}}" wx:key="???">不能被复用,但是不想看到警告</view>

      2019-05-19
      回复
    • LastLeaf
      LastLeaf
      2019-05-21回复卢丑丑

      一、在 key 无效的情况下,我们会尝试去复用已有的节点(包括自定义组件)。这个过程会更改自定义组件属性。

      二、现在应该都会给警告。

      2019-05-21
      1
      回复
    • 小小发
      小小发
      2019-12-23
      wx:key不能不吐槽一下,用的真糟心
      2019-12-23
      回复
  • 赵有
    赵有
    2020-06-18

    List 结构是这种,怎么指定 wx:key 呢?(我需要a里面的id)

    [
      {
         'a': { 'id': 1}
         'b': {'name': 'xxx'}
      },
      {
         'a': { 'id': 2}
         'b': {'name': 'yyyy'}
      }
    ]
    


    2020-06-18
    有用
    回复 1
    • 梦尋 # Junjie  🍂
      梦尋 # Junjie 🍂
      08-29
      在渲染之前 使用js 修改数据结构 这样就可以了 除了麻烦 全是缺点   哈哈哈哈哈哈
      08-29
      回复
  • 明明就
    明明就
    2019-07-24

    你好,我这边用了wx:key="unique",但是重新打乱了顺序之后,input的值被改回去了?这是怎么回事,我按照网上的一个例子做的也不行

    <input wx:for="{{inputList}}" wx:for-item="dItem" wx:key="unique" value="id:{{dItem.id}}" />

    <button bindtap="switch">switch</button>

    <button bindtap="addToFront">addToFront</button>


    Page({

    data: {

    logs: [],

    inputList: [{

    "id": 1,

    "unique": "unique1"

    },

    {

    "id": 2,

    "unique": "unique2"

    },

    {

    "id": 3,

    "unique": "unique3"

    },

    {

    "id": 4,

    "unique": "unique4"

    },

    ]

    },

    addToFront: function(e) {

    const length = this.data.inputList.length + 1;

    this.data.inputList = [{

    id: length,

    unique: 'unique_' + length

    }].concat(this.data.inputList)

    this.setData({

    inputList: this.data.inputList

    })

    },


    switch: function(e) {

    const length = this.data.inputList.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.inputList[x]

    this.data.inputList[x] = this.data.inputList[y]

    this.data.inputList[y] = temp

    }

    this.setData({

    inputList: this.data.inputList

    })

    },


    2019-07-24
    有用
    回复
  • 赵青山
    赵青山
    2019-05-16

    wx:key="{{ item.id }}"    当然是错的啦,key就是属性名,这里写成item.id,那就是拿item.id的值当key,当你改变数组的时候,它会报key相同的警告,


    正确应该是wx:key="id"

    2019-05-16
    有用
    回复 10
    • 卢丑丑
      卢丑丑
      2019-05-16

      项目里很多地方都这么用了,不会报警告的,这个是确定的。你的意思是wx:key="{{item.id}}",会先解析花括号里的表达式,然后把这个表达式的值当成key,也就是说最后列表项的唯一标识会是item[ item[id] ],一般来说就是undefined,是这意思吧?


      嗯的,我知道正确的写法是啥,但是我更想知道,在错误写法的时候发生了什么。


      我提供了两个示例,有针对性的,可以看看

      2019-05-16
      回复
    • 赵青山
      赵青山
      2019-05-16

      那个key是用来复用组件的,如果key写的不对,渲染时则找不到对应的组件,组件就会重新创建而不会复用,仅此而已

      2019-05-16
      回复
    • 卢丑丑
      卢丑丑
      2019-05-16回复赵青山

      那你再看看第二个示例,看是这样么

      2019-05-16
      回复
    • 赵青山
      赵青山
      2019-05-16

      只是视图层重新渲染了,逻辑层并没有变化

      2019-05-16
      回复
    • 卢丑丑
      卢丑丑
      2019-05-16回复赵青山

      “只是视图层重新渲染了,逻辑层并没有变化”

      那岂不是比用wx:key="unique"还好?wx:key的意义何在?

      视图层自己就变了?mvvm的思路不就是逻辑层决定视图层?

      哎老弟,对待知识应该严谨,你再想想是真懂了么?

      2019-05-16
      回复
    查看更多(5)
  • YYW
    YYW
    2019-05-16

    写惯了vue当初也有这个疑问

    2019-05-16
    有用
    回复
登录 后发表内容