Как визуализировать компонент в v-for кнопкой от родителя - PullRequest
0 голосов
/ 19 января 2019

Как я могу визуализировать компонент v-if кнопкой (кнопка в родительском элементе) внутри цикла v-for?и должен отображаться только в том элементе, где нажал

<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>

Ответы [ 3 ]

0 голосов
/ 19 января 2019

Вы должны хранить информацию о состоянии каждого элемента (если он был нажат) в ваших данных. Затем, когда вы нажимаете на кнопку, вы должны обновить свойство 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>
0 голосов
/ 19 января 2019

Просто и просто, вам просто нужно установить какой-нибудь флаг для последних 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

0 голосов
/ 19 января 2019

Вы можете воспользоваться индексом элемента ..., доступным в директиве 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>
...