vue+Element UI enables one line card list to switch from left to right

vue+Element UI implements a card list. Click left and right to switch the rotation

Foreword: Based on a demand in the project, it is necessary to display some material lists on the home page. Each material card is displayed in the list. The material list is displayed in one line, and up to 5 cards are displayed in one line. When there are more than five cards, the left and right arrows will appear. Clicking the arrows can move the card list left and right, which is similar to the rotation chart. The difference is that the rotation chart can only be seen one at a time, while this example can see up to 5 cards at a time

There are no relevant components in the element UI component library. Only Carousel has a riding light, but it doesn't meet the requirements. I began to think about using arrays, but this can't achieve excessive effects. There are no relevant examples found on the Internet. Then I'll do it myself. I wrote a demo, which is just a record. There are many optimization places. Let's start

First up effect:

realization:

  1. Create project demo and import Element UI component library
// The scrouter command is used to create the project
 vue create demo 
 
// Import component main JS inside
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
Vue.use(ElementUI);
 
 // Introduce your own css style file
 import './assets/css/index.css'

  1. To create a page, my idea is to package the card of each item into a component, then introduce the component into the display page, and cycle with the requested data to get the list. Therefore, I need to create a card component under src/components, a page under views, and then introduce the card component into the page component

The file directory is as follows

3. Start writing pages
card component (i.e. swiper/index.vue)
I just wrote a simple idea here, so the data in it is written directly. It is true that the data in development should be transmitted through the parent component, such as the content of the card, and then the click event of each card can be transmitted to the parent component for processing. Of course, it is not written here
Here: style="{minWidth:width}" is to dynamically adapt the screen. No matter how the screen changes, only five cards are visible in the viewing area

<template>
 <div class="card-item" :style="{minWidth:width}">
  <el-card :body-style="{ padding: '0px' }">
      <img src="https://shadow.elemecdn.com/app/element/hamburger.9cf7b091-55e9-11e9-a976-7f4d0b07eef6.png" class="image">
      <div style="padding: 14px;">
        <span>Delicious hamburger</span>
        <div class="bottom clearfix">
          <time class="time">{{ currentDate }}</time>
          <el-button type="text" class="button">Operation button</el-button>
        </div>
      </div>
    </el-card>
 </div>
</template>

<script>
 export default {
   props:{
       width:{
           type:String,
           default:"20%"
       }
   },
   data () {
     return { 
          currentDate: new Date()
     }
   },
 }
</script>

<style lang='scss' scoped>
.card-item {
    padding:10px;
    box-sizing: border-box;
}
  .time {
    font-size: 13px;
    color: #999;
  }
  
  .bottom {
    margin-top: 13px;
    line-height: 12px;
  }

  .button {
    padding: 0;
    float: right;
  }

  .image {
    width: 100%;
    display: block;
  }

  .clearfix:before,
  .clearfix:after {
      display: table;
      content: "";
  }
  
  .clearfix:after {
      clear: both
  }
</style>
  1. Then home Vue inside
    This page is just written briefly, mainly to achieve the effect. There are many places that can be optimized. For example, the left and right arrows can be hidden and displayed when the number of cards is less than 5. hover will not be displayed when the number of cards is less than 5, and so on,
<template>
  <div class="home">
   <el-row :gutter="20" type="flex" justify="center">
      <el-col :span="20">
        <div id="father" class="grid-content bg-purple">
          <div id="swiper-box" class="swiper-box" :style="{transform:'translateX('+currentOffset+'px)'}">
           <swiper-item  :width="width" v-for="i in 10"></swiper-item>
          </div>
          <i class="el-icon-arrow-left" @click="left"></i>
          <i class="el-icon-arrow-right" @click="right"></i>
        </div>
      </el-col>
      
    </el-row>
    
  </div>
</template>

<script>
// @ is an alias to /src
import swiperItem from '@/components/swiper'

export default {
  name: 'Home',
  data() {
    return {
      currentOffset:0,
      width:"",
      fatherWith:0,
      box:'' // dom
    }
  },
  components: {
    swiperItem
  },
  mounted () {
    this.setCardWidth()
    this.box = document.querySelector('#swiper-box')
    window.addEventListener('resize',()=>{
      this.currentOffset = 0
      this.setCardWidth()
    })
  },
  methods:{
    setCardWidth() {
      const father = document.querySelector('#father');
      this.fatherWith = father.clientWidth
      console.log("fatherWidth",this.fatherWith);
      this.width = ((this.fatherWith-20) / 5)+'px'
    },

    right() {
      console.log(this.currentOffset);
      if(this.currentOffset <= (-(this.fatherWith-20) / 5)*(10-5)) return
      this.currentOffset-=((this.fatherWith-20) / 5)
    },
    left() {
      console.log(this.currentOffset);
      if(this.currentOffset >= -2) return
      this.currentOffset+=((this.fatherWith-20) / 5)
    }
  }
}
</script>


<style lang="scss" scoped>
.bg-purple {
  overflow: hidden;
  position:relative;
  padding-left: 10px;
}
.home {
  margin-top: 50px;
  .swiper-box {
    display: flex;
    width: auto;
    transition: all .2s;
  }
}

[class ^="el-icon-arrow-"] {
  position:absolute;
  top:50%;
  transform: translateY(-50%);
  font-size: 30px;
  padding: 10px 0;
  background-color: #999;
  cursor: pointer;
  
}
.el-icon-arrow-left, {
  left:-7px;
}
.el-icon-arrow-right, {
  right:-7px;
}
</style>

So far, it is simple to realize. There are many optimization and improvement places, just a little record of yourself. Please indicate the source for reprint. Thank you

Tags: Javascript ECMAScript Vue Vue.js

Posted by chigley on Wed, 04 May 2022 01:34:03 +0300