因为需要做了一个相册的业务组件,我感觉还挺难看的,分享给大家看一下,能够本人提取,6点几了,上班先!

<template>  <div class="img-wrapper">    <el-button      icon="h-icon-angle_left"      plain      class="left to"      :disabled="disabledPrev"      @click="toRight"    ></el-button>    <div ref="imagesWrapper" class="images">      <div v-if="noData" class="empty-text">        <slot name="empty">暂无数据</slot>      </div>      <div v-show="!noData" class="items" :style="itemsStyle">        <div          v-for="(item, index) in data"          :key="index"          class="item-img"          :style="imgSize"          :class="{            'is-active': index === currentIndex          }"          @click="selected(index)"        >          <img :title="item[props.title]" :src="item[props.url]" />          <p v-if="item[props.title]" v-ellipsis class="item-date">            {{ item[props.title] }}          </p>        </div>      </div>    </div>    <el-button      icon="h-icon-angle_right"      :disabled="disabledNext"      plain      class="right to"      @click="Left"    ></el-button>  </div></template><script>export default {  name: 'ImagesGroup',  props: {    imgSize: {      type: Object,      default: () => {        return {          width: '120px',          height: '120px'        };      }    },    value: {      type: Number,      default: null    },    data: {      type: Array,      default: () => []    }  },  data() {    return {      props: {        title: 'title',        url: 'url',        key: 'key',        type: 'type'      },      currentIndex: '',      translateX: 0,      pageSize: 0 // 一页展现的图片数    };  },  computed: {    // 偏移度数    itemsStyle() {      return {        transform: `translateX(${-this.translateX}px)`      };    },    // 每一项宽度    itemWidth() {      return parseInt(this.imgSize.width.replace('px', '')) + 8;    },    disabledPrev() {      // 禁用前一页按钮      return this.translateX <= 0;    },    disabledNext() {      // 禁用后一页按钮      return (        this.translateX >= (this.data.length - this.pageSize) * this.itemWidth      );    },    noData() {      return this.data.length === 0;    },    dataLength() {      return this.data.length;    }  },  watch: {    value: {      immediate: true,      handler(val) {        this.currentIndex = val;      }    }  },  mounted() {    this.pageSize = this.wrapperWidth() / this.itemWidth;  },  methods: {    toRight() {      if (this.translateX < this.pageSize * this.itemWidth) {        this.translateX = 0;      } else {        this.translateX = this.translateX - this.pageSize * this.itemWidth;      }    },    Left() {      this.translateX = this.translateX + this.pageSize * this.itemWidth;      const maxTrans = this.itemWidth * (this.dataLength - this.pageSize);      if (this.translateX > maxTrans) {        this.translateX = maxTrans;      }    },    selected(index) {      const center = this.pageSize >> 1;      // 最初一页的两头地位      const lastCenter = this.dataLength - center;      if (index > center && index < lastCenter) {        // 与相册两头相差的图片数量        const step = index - center;        // 将点击图片挪动到两头        this.translateX = this.itemWidth * step;      } else {        const maxTrans = this.itemWidth * (this.dataLength - this.pageSize);        this.translateX = index <= center ? 0 : maxTrans;      }      if (this.currentIndex !== index) {        this.currentIndex = index;        this.$emit('input', index);      }    },    wrapperWidth() {      if (this.$refs.imagesWrapper) {        return this.$refs.imagesWrapper.offsetWidth;      }      return 0;    }  }};</script><style lang="less" scoped>.img-wrapper {  display: flex;  position: relative;  margin: 20px;  height: 120px;  .to {    width: 32px;    height: 100%;    padding: 0;  }  .images::before {    position: absolute;    z-index: 5;    top: 0;    height: 100%;    width: 84px;    content: '';    pointer-events: none;    background: -webkit-gradient(      linear,      left top,      right top,      from(#fff),      color-stop(50%, rgba(0, 0, 0, 0))    );    background: -o-linear-gradient(left, #fff, rgba(0, 0, 0, 0) 50%);    background: linear-gradient(90deg, #fff, rgba(0, 0, 0, 0) 50%);  }  .images::after {    position: absolute;    z-index: 5;    top: 0;    height: 100%;    right: 0;    width: 84px;    content: '';    pointer-events: none;    background: -webkit-gradient(      linear,      right top,      left top,      from(#fff),      color-stop(50%, rgba(0, 0, 0, 0))    );    background: -o-linear-gradient(right, #fff, rgba(0, 0, 0, 0) 50%);    background: linear-gradient(270deg, #fff, rgba(0, 0, 0, 0) 50%);  }  .images {    position: relative;    overflow: hidden;    width: 100%;    height: 100%;    margin: 0 2px;    .empty-text {      color: rgb(158, 158, 158);      height: 100%;      display: flex;      align-items: center;      justify-content: center;    }    .items {      position: absolute;      top: 0;      left: 0;      display: flex;      // width: 6000px;      height: 100%;      align-items: center;      transition: transform 0.25s ease;      .item-img {        display: inline-block;        box-sizing: border-box;        position: relative;        margin-right: 8px;        border: 2px solid rgba(0, 0, 0, 0);        cursor: pointer;        .item-date {          bottom: 0px;          position: absolute;          width: 100%;          height: 24px;          background: rgba(0, 0, 0, 0.2);          text-align: center;          line-height: 24px;          color: white;        }        img {          width: 100%;          height: 100%;        }      }      .item-img:hover::after {        // border-color: #409EFF;        opacity: 0;      }      .item-img::after {        position: absolute;        top: 0;        left: 0;        width: 100%;        height: 100%;        content: '';        opacity: 0.2;        pointer-events: none;        -webkit-transition: opacity 0.3s ease;        -o-transition: opacity 0.3s ease;        transition: opacity 0.3s ease;        background-color: #fff;      }      .is-active {        border-color: #409eff;      }      .is-active:after {        opacity: 0;      }    }  }}</style>