How to insert Vue component in dynamic position?

2019-05-25 21:42发布

Lots of panels (product) are showing in a page in multiple row and multiple column. I'm using Vue 2 and panels are components. Now, on clicking a panel, I want to show details of that panel below the row of that. This is similar to Google image search.

enter image description here

For example, in the above image, if I click any of the s1, s2 or s3, the big panel will appear after s3 (last element of that row). Similarly, for clicking s4 or s5, the big panel appear after s5.

** Number of items in a row will vary based on the screen size.

How to find the last element of the row and insert a component after that element?

2条回答
一纸荒年 Trace。
2楼-- · 2019-05-25 22:21

If you want to arrange the components: one will appear after another. Let me assume I have all those components in an array and you can re-arrange those in the array as par your logic, and you can use special attribute: is to render those component.

Here in sample I have an array of components and I use v-for to render those one after another:

See fiddle here.

HTML:

<div id="app">
  <h1>
  Following are the components
  </h1>
  <div v-for="comp in compArray" :is="comp"></div>
  <br>
  <button @click="resuffle">
     Resuffle
  </button>
</div>

<template id="comp1">
  <div>
    <span>This is component 1</span>
  </div>
</template>

<template id="comp2">
  <div>
    <span>This is component 2</span>
  </div>
</template>

<template id="comp3">
  <div>
    <span>This is component 3</span>
  </div>
</template>

JS:

Vue.component('comp1', {
  template: '#comp1', 
})

Vue.component('comp2', {
  template: '#comp2', 
})
Vue.component('comp3', {
  template: '#comp3', 
})

new Vue({
    el: '#app',
  data: {
    compArray: ['comp1', 'comp2', 'comp3']
  },
  methods: {
    resuffle: function() {
       this.compArray.push(this.compArray[1])
       this.compArray.splice(1,1)
    }
  },
})
查看更多
Melony?
3楼-- · 2019-05-25 22:31

This does not answer your question directly, but should implement the expected behavior. Here is a jsfiddle

Template:

<div id="vue-instance">
  <ul class="item-list">
    <li class="item" v-for="item in inventory" @click="dispalyDetails(item)">
      <div class="header">{{ item.name }} - ${{ item.price }}</div>
      <div v-if="item.displayed" class="details">
        <div class="details__inner">
          {{ item.details }}
        </div>
      </div>
    </li>
  </ul>
</div>

Vue:

var vm = new Vue({
  el: '#vue-instance',
  data: {
    inventory: [
      {name: 'MacBook Air', price: 1000, details: 'Lorem ipsum', displayed: false},
      {name: 'MacBook Pro', price: 1800, details: 'Lorem ipsum', displayed: false},
      {name: 'Lenovo W530', price: 1400, details: 'Lorem ipsum', displayed: false},
      {name: 'Acer Aspire One', price: 300, details: 'Lorem ipsum', displayed: false},
      {name: 'Aspire One', price: 700, details: 'Lorem ipsum', displayed: false}
    ]
  },
  methods: {
    deselectItems() {
        this.inventory.forEach((item) => {
        item.displayed = false;
      });
    },
    dispalyDetails(item) {
        if (!item.displayed) {
        this.deselectItems();
      }

        item.displayed = !item.displayed;
    }
  }
});

Scss:

.item-list {
  position: relative;
  display: flex;
  flex-wrap: wrap;
  width: 80%;
  margin: 0 auto;
}

.item {
  width: 33.33%; // adjust accordingly in mq
  box-sizing: border-box;
}

.header {
  box-sizing: border-box;
  padding: 10px;
}

.details {
  border: 1px solid red;
  min-height: 200px;
}

.details__inner {
  position: absolute;
  left: 0;
  width: 100%;
  min-height: 200px;
  border: 1px solid green;
}
查看更多
登录 后发表回答