uni-app 使用v-for指令渲染自定义组件,props传参出现重大问题,

daupos2t  于 2021-11-27  发布在  Java
关注(0)|答案(3)|浏览(287)

问题描述

前提:使用v-for指令渲染自定义组件,列表数据动态,自定义组件的props依赖列表的数据(如length,index)。
结果:自定义组件内部状态在列表数据发生改变时,无法同步改变。

复现步骤

代码:

<!-- 列表渲染自定义组件 -->
<template>
  <view class="content">
    <item
      v-for="(item, index) in list"
      :key="item.key"
      :length="list.length"
      :index="index">
    </item>
    <button class="button" @click="addItem">
      列表加一项
    </button>
  </view>
</template>

<script>
import item from './item.vue'
export default {
  name: 'index',
  components: {
    item
  },
  data () {
    return {
      list: [],
      key: 0
    }
  },
  methods: {
    addItem () {
      this.list.push({ key: this.key++ })
    }
  }
}
</script>
<!-- 自定义组件 -->
<template>
  <view class="content">
    {{length}}
  </view>
</template>

<script>
export default {
  name: 'item',
  props: {
    length: Number
  }
}
</script>

操作

点击按钮任意次数

预期结果

点击按钮添加列表数据,每个自定义组件可以获取列表长度。

实际结果

每个自定义组件只能获取到创建时的列表长度

系统信息:

  • 发行平台: [如 微信小程序、H5平台、5+ App等]
  • 操作系统 [如 iOS 12.1.2、Android 7.0]
  • HBuilderX版本 [如使用HBuilderX,则需提供 HBuilderX 版本号]
  • uni-app版本 v2.7.9
  • 设备信息 [如 iPhone8 Plus]

补充信息

[可选]
[根据你的分析,出现这个问题的原因可能在哪里?]

r7s23pms

r7s23pms1#

后续提问题,最好标明详细信息,比如哪个平台,不然测试半天才知道是什么问题
这是微信小程序底层Bug:https://developers.weixin.qq.com/community/develop/doc/000c8ee47d87a0d5b6685a8cb57000
解决方案,使用计算属性:

computed: {
            len() {
                return this.list.length
            }
        },
nr9pn0ug

nr9pn0ug2#

抱歉!这个问题是确实是运行在微信小程序出现的。感谢开发者!不过这看起来并不是这条连接所提到的全量更新与差量更新问题。而是v-for指令参数作用域的问题。可以看下这个例子

列表渲染order组件
<template>
  <view class="content">
    <view
      v-for="(item, index) in list"
      :key="item.oid"
      style="margin-bottom: 10px">
      <view>
        父组件中的length: {{list.length}}
      </view>
      <view>
        父组件中的oid: {{item.oid}}
      </view>
      <view>
        父组件中的index: {{index}}
      </view>
      <view>
        -----------
      </view>
      <order
        :length="list.length"
        :oid="item.oid"
        :index="index">
      </order>
      <view>
        ====================================================
      </view>
    </view>
    <button class="button" @click="addItem">
      列表加一项
    </button>
    <button @click="reverse">
      倒序
    </button>
  </view>
</template>

<script>
import order from './order.vue'
export default {
  name: 'index',
  components: {
    order
  },
  data () {
    return {
      list: [],
      key: 0
    }
  },
  methods: {
    addItem () {
      this.list = this.list.concat([{ oid: this.key++ }])
    },
    reverse () {
      this.list.reverse()
    }
  }
}
</script>
order组件
<template>
  <view class="content">
    <view>
      自定义组件中的length{{length}}
    </view>
    <view>
      自定义组件中的oid{{oid}}
    </view>
    <view>
      自定义组件中的index{{index}}
    </view>
  </view>
</template>

<script>
export default {
  name: 'order',
  props: {
    length: Number,
    oid: Number,
    index: Number
  }
}
</script>
操作

点击新增两次
点击倒序

预期结果

order组件在父组件中成功倒序,且列表index数据正常

实际结果

order组件在父组件中成功倒序,但是index未能成功更换

rqcrx0a6

rqcrx0a63#

1.我上条回复,解决的是length不同步变化的问题,这个是小程序底层Bug导致
2.你最新回复里的index问题,这个结果是正确的,你只是倒序了list,但是父组件v-for里边的index,还是从0开始计数,所以父组件里的index,始终都是0,1,2,3....,子组件之所以没问题,是因为index通过prop做了值传递

举个简单的纯js例子

const list = [0,1];
for(let index=0;index<list.length;index++){
console.log(index,list[index])
}
//输出结果
// 0 0
// 1  1
list.reverse()
for(let index=0;index<list.length;index++){
console.log(index,list[index])
}
//输出结果(此时index不可能发生变化的)
// 0 1
// 1  0

相关问题