如何通过父级按钮在 v-for 中渲染组件

Posted

技术标签:

【中文标题】如何通过父级按钮在 v-for 中渲染组件【英文标题】:How render component in v-for by button from parent 【发布时间】:2019-06-13 09:55:18 【问题描述】:

如何通过按钮(父级按钮)在 v-for 循环内单击来呈现 v-if 组件?并且应该只在点击的那个项目中呈现

<div v-for="item in items">
  <button @click >Show child<button>
  <div>item.name</div>
  <child v-if="this button clicked" :item="item"><child>
<div>

【问题讨论】:

同时显示您的items 内容 不管。它类似于输入方法来提交存储 item.newtext 和来自输入的信息(它工作正常) @RemiFokz 我以前解决过类似的问题,请查看 this post 并告诉我它是否适合您。 【参考方案1】:

您必须在数据中存储有关每个项目(如果被点击)的状态信息。然后,当您单击按钮时,您应该更新特定项目的 clicked 属性。最后,如果 item.clicked 设置为 true,您将显示您的子组件(或任何其他 html)。

<template>
  <div>
    <div v-for="item in items" :key="item.id">
      <button @click="item.clicked = true" >Show child</button>
      item.name
      <div v-if="item.clicked">Item child</div>
    </div>
  </div>
</template>

<script>
export default 
  name: 'HelloWorld',
  data: function() 
    return 
      items: [
        
          id: 1,
          name: 'test1',
          clicked: false
        ,
        
          id: 2,
          name: 'test2',
          clicked: false
        ,
        
          id: 3,
          name: 'test3',
          clicked: false
        
      ]
    
  

</script>

【讨论】:

我正在从商店获取项目(大对象数组),但不确定是否需要向它们添加更多属性【参考方案2】:

简单明了,您只需为后者设置一些标志v-if

<div id="app">
  <div v-for="item in items">
    <button @click="$set(item, 'shown', true)">Show child</button>
    <div> item.name </div>
    <div v-if="item.shown">Child component</div>
  </div>
</div>

这里使用$set(),因为初始item 可能缺少shown 字段,因此直接使用item.shown=true 设置它不会产生反应。

您也可以在点击后隐藏按钮:

<button @click="$set(item, 'shown', true)" v-if="!item.shown">Show child</button>

切换可见性,您只需这样做:

<button @click="$set(item, 'shown', !item.shown)">
   item.shown ? 'Hide' : 'Show'  child
</button>

JSFiddle

【讨论】:

@RemiFokz 用切换变体更新了我的答案【参考方案3】:

您可以利用 v-for 指令(例如 v-for="(item, i) in items")中提供的项目...索引,将其(项目的索​​引)绑定到通过更改项目属性来显示项目的函数:

更新:在需求细化后,初始答案已被删除。

由于您希望避免项目的变化,您可以将它们包装在 Map 对象(作为键)中,并将可见性设置单独保存为 Map 值。不幸的是,据我所知,Vue.js 暂时不支持Map 对象的反应性,这就是为什么我必须使用forceUpdate 手动触发重新渲染:

Vue.config.devtools = false;
Vue.config.productionTip = false;
Vue.component('child', 
  template: '<p>Visible child</p>'
)

new Vue(
  el: "#demo",
  template: `
<div>
  <div v-for="item in items">
    <button @click="toggleChild(item)">Toggle child</button>
    <div>item.name</div>
    <child v-if="isVisible(item)" :item="item"></child>
  </div>
</div>
`,
  data () 
    return 
      itemsMap: new Map(
        [
           name: 'test1' ,
           name: 'test2' 
        ].map(item => [item,  visible: false ])
      )
    ;
  ,
  methods: 
    toggleChild(item) 
      this.itemsMap.set(item,  visible: !this.itemsMap.get(item).visible );
      this.$forceUpdate();
    ,
    isVisible(item) 
      return this.itemsMap.get(item).visible;
    
  ,
  computed: 
    items: function() 
      return Array.from(this.itemsMap.keys());
    
  
)
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="demo"></div>

【讨论】:

我正在从商店获取项目(大对象数组),但不确定是否需要向它们添加更多属性 @RemiFokz 嗨,我已经用一个不会改变原始项目的变体更新了答案,希望它可能会有所帮助。

以上是关于如何通过父级按钮在 v-for 中渲染组件的主要内容,如果未能解决你的问题,请参考以下文章

Bootstrap-Vue 模态:如何在 V-For 渲染列表中打开不同的模态?

Vue.js 中父级数据更改时如何重新渲染内部组件

Vues - 如何在渲染函数中使用 v-for 和作用域插槽

如何避免重新渲染由 v-for 指令创建的所有子组件

控制台警告:用 v-for 渲染的组件列表应该有明确的键

使用 Vue 在 v-for 中进行条件渲染