v-for inside v-for 在 onclick 事件中显示数据

Posted

技术标签:

【中文标题】v-for inside v-for 在 onclick 事件中显示数据【英文标题】:v-for inside v-for displaying data in onclick event 【发布时间】:2021-09-26 05:05:34 【问题描述】:

大家好,我有对象数组,在每个对象内部我也有对象数组.. 我在 v-for 里面做了 v-for 来显示数据 起初我希望每一行显示父数组和 onClick 事件的每个子元素的第一个元素的数据,我只想更改特定行中的数据。

infos: [
    name: 'name1',
    infosName: [
        place: 'place.1.1',
        surface: '100'
      ,
      
        place: 'place.1.2',
        surface: '200'
      
    ]
  ,
  
    name: 'name2',
    infosName: [
        place: 'place.2.1',
        surface: '300'
      ,
      
        place: 'place.2.2',
        surface: '400'
      
    ]
  
]

我创建了一个方法来显示数据并获得了参数两个索引 这是一个 jsfiddle 以了解更多问题

谢谢

https://jsfiddle.net/f0ehwacm/2

【问题讨论】:

请准确显示您期望的结果,因为这个描述似乎有点模棱两可。 @RoboRobok 谢谢你的回答,我想要的是当你点击跨度(在 fiddljs 中)时,它会显示正确的信息,但我的代码没有显示正确的信息,但是它也在其他行中发生了变化 再次,请准确显示结果,因为 - 引用 - “起初我希望每一行显示父数组和 onClick 事件的每个子元素的第一个元素的数据,我想要仅更改特定行中的数据。” - 听起来不是很清楚。 请查看 jsfidle 以了解我在说什么,在我想要的示例中,当您单击特定跨度时,您会显示数组的特定索引的数据 好吧,我不认为我们互相理解。再见。 【参考方案1】:

有几个问题需要解决,但你是正确的。

最重要的是,您不仅需要存储一个“myIndex”,还需要为每一行存储一个单独的“myIndex”

这是你问题的根本原因。

让我改一下你的问题?

我相信您希望有四个按钮。顶部的两个按钮在两个选项之间进行选择。

完全分开,底部的两个按钮在两个选项之间进行选择。

如果您将顶部的两个按钮称为“问题 1,选项 A”和“问题 1,选项 B”,读者会更容易理解您的意图。然后是底部的两个“问题2 ...”。然后他们就会明白为什么当您单击其中一个按钮时,您只想影响该行的表格输出。

避免使用“index”和“i”等通用术语

这些使人们不必要地难以理解您的意图。最好使用具体名词,在这种情况下为“问题”或“答案”,当您表示索引时,在其前面加上“i”,例如“iQuestion”表示问题的索引,“question”表示问题本身.

您似乎只有一个函数“getInfos”,它可以同时获取和设置信息

这是一个大问题。您应该将这两个功能分开。

当你点击时,你想运行一个“set”函数来更新你的索引。

当您只是显示时,您可以访问“get”函数,该函数不会改变任何内容。

你需要为每一行存储一个索引

用我的术语来说,你需要存储你对每个问题的答案的索引。

所以 this.myIndex 不是从 0 开始,而是从 [0,0] 开始。这两个值中的每一个都可以单独更新,从而允许程序更新一行(即一个问题)的答案,而另一行保持不变。

我已将此变量重命名为 this.myAnswer 以便于理解。

this.$set 写入您希望 Vue 响应的数组时

我最初写的“setAnswer”函数如下:

this.myAnswer[iQuestion]=iAnswer  

但是,我发现屏幕显示没有更新。这是 Vue 中的一个常见问题,当您更新的不是data() 中列出的主属性,而是该属性的数组元素。

这是因为 Vue 不跟踪数组元素的更新,只跟踪数组本身。因此,如果您要重新分配整个数组,Vue 会注意到。

解决方法是明确告诉 Vue 你正在更新一些需要反应的东西。然后 Vue 会在屏幕上更新它。

为此,请从以下格式更改您的作业:

this.array[index] = value

到这里

this.$set(this.array, index, value)

Vue 提供了这个函数this.$set,它执行你正常的this.array[index] = value并且告诉 Vue 进行屏幕更新。

如何处理丢失的“infosName”

在 cmets 中回答您的问题。你有一个方便的地方来解决这个问题:getAnswer() 函数。

从此改变:

getAnswer(iQuestion,iAnswer)
    return 
    'name' : this.infos[iQuestion].infosName[iAnswer].place,
    'surface' : this.infos[iQuestion].infosName[iAnswer].surface
  

到这里:

getAnswer(iQuestion,iAnswer)
    if (this.infos.length>iQuestion &&
        this.infos[iQuestion].infosName &&
        this.infos[iQuestion].infosName.length>iAnswer 
    )
        return 
            'name' : this.infos[iQuestion].infosName[iAnswer].place,
            'surface' : this.infos[iQuestion].infosName[iAnswer].surface
        
    else return 
    name : "",
    surface: ""

解决方案

html:

<div id="app">
    <div v-for="(question,iQuestion) in infos">
        <div class="row d-flex">
<span style="margin-right:10px" v-for="(answer,iAnswer) in question.infosName" class="badge badge-primary" @click="setAnswer(iQuestion,iAnswer)"><i class="fa fa-eye" style="margin-right:10px;cursor: pointer"></i> answer.place </span>        </div>
        <div class="row">
             <p>Name :  getAnswer(iQuestion,myAnswer[iQuestion]).name  </p>
            <p>Surface :  getAnswer(iQuestion,myAnswer[iQuestion]).surface </p>
        </div>
    </div>
</div>

JS:

new Vue(
    el :'#app',
  data : function()
    return 
        myAnswer : [0,0],
    infos : [
            
            name : 'name1',
          infosName : [
                
                place : 'Question 1, Option A',
                surface : '100'
              ,
              
                place : 'Question 2, Option B',
                surface : '200'
              
          ]
        ,
        
            name : 'name2',
          infosName : [
                
                place : 'Question 2, Option A',
                surface : '300'
              ,
              
                place : 'Question 2, Option B',
                surface : '400'
              
          ]
        
    ]
    
  ,
  methods:
  setAnswer(iQuestion,iAnswer)
        this.$set(this.myAnswer,iQuestion,iAnswer)  
  ,
  
    getAnswer(iQuestion,iAnswer)
        return 
        'name' : this.infos[iQuestion].infosName[iAnswer].place,
        'surface' : this.infos[iQuestion].infosName[iAnswer].surface
      
    
  
)

【讨论】:

谢谢你的好答案,我会把答案标记为正确的,我自己调整你的代码,它按预期工作谢谢,我有 2 个问题,1 - 这是什么.$refs 做了吗? 2 - 例如在 infos[] 数组中我们有 3 个对象,前 2 个对象与上面提到的代码相同,第三个对象的 infosName[] 数组为空,它会抛出错误再次感谢您 不客气! 8-) 我已经为你的两个问题添加了答案。 (我认为您的意思是 this.$set,而不是 this.$refs) 你好@Eureka,我只想说,如果我们在 infos[] 数组中有 3 个对象并且所有内容都不为空,它会抛出一个错误,我想知道 myAnswer : [0 ,0] 是prblm im i的原因吗?谢谢你 我认为你的意思是“所有的东西 is null”,而不是“所有的东西都 not null”。不是将 myAnswer 设置为 [0,0] 会导致错误。它正在尝试读取空数组的 [0] 元素。我已经更新以避免这种情况。如果数组可能没有足够的元素,则在读取特定元素之前进行检查是一种很好的做法

以上是关于v-for inside v-for 在 onclick 事件中显示数据的主要内容,如果未能解决你的问题,请参考以下文章

Vue.js v-if inside v-for 不主动监听数组变化

在 v-for 组件中删除了错误的项目 [在 v-for 中选择正确的 :key]

5.v-for

v-for

v-if和v-for

5.10v-for