element显示true或者false_element-ui轮播的简单实现

这段时间,一直在学习些源码,想了解下大佬的思路,看完后,只能说卧槽,还有这种操作。

element-ui一个Vue常用的组件库,包含很多的知识点可以学习,其很多组件只是样式的变化。难度比较大的,轮播算一个。今天就给大家简单实现下它的一系列操作。

首先它分为两个组件,一个是父组件(容器),另一个是子组件(幻灯片),首先容器是固定一个窗口,让对应的幻灯片显示。

我们先来写好它的模版。

父组件

<div class="n-slide">
    <div class="n-slide-container" :style="{height: height}">
      <slot></slot>
    </div>
</div>
.n-slide-container {
    position: relative;
    overflow: hidden;
  }

子组件

<template>
  <div v-show="ready" :class="['n-slide-item',{animating}]" :style="translateStyle">
    <slot></slot>
  </div>
</template>
.n-slide-item {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    overflow: hidden;
    z-index: 0;

    &.animating {
      transition: transform 0.4s ease-in-out;
    }
  }

容器样式参数,只接受一个高度,宽度是自适应的。

b94cfa2adeabdcaadce08583a1e8aad1.png

这是文档上记录的可传递的参数。

下面我们按照,这些传递的参数简单实现下它的功能。
<script>
  export default {
    name: 'Slide',
    props: {
      loop: {
        type: Boolean,
        default: true
      },
      autoplay: {
        type: Boolean,
        default: true
      },
      height: String,
      interval: {
        type: Number,
        default: 3000
      },
      initialIndex: {
        type: Number,
        default: 0
      }
    },
  }

暂时,我们就只需要这些。实现一下自动滚动的功能。

首先我们需要加载幻灯片,看看有多少个:

父组件

data() {
  return {
    items: [],
    }
},
methods: {
  upDataItems() {
        this.items = this.$children.filter(child => child.$options.name === 'NSlideItem')
    }
 }

子组件

created() {
      this.$parent && this.$parent.upDataItems()
 }

这里加载幻灯片是通过,子组件的created函数调用父组件的upDataItems函数实现的。

这里如果不懂的同学,可以好好了解下Vue的生命周期,当父组件和子组件在一起时,生命周期是怎样的运作过程。就不详细阐述了。

加载完后,我们需要让轮播滚动起来。

父组件

mounted() {
        // 为了确保幻灯片加载完
    this.upDataItems()
    // $nextTick是把执行逻辑放入Vue的异步队列中,等Vue的事件初始化完成后才会执行,为了正确的给activeIndex赋值,否则初始化轮播为最后一张
    this.$nextTick(() => {
        if (this.initialIndex < this.items.length && this.initialIndex >= 0) {
          this.activeIndex = this.initialIndex;
        }
        // 打开定时器
        this.startTimer();
      });
    },
data: {
  items: [],
  timer: null,
  initIndex: 0, // 初始的index
  activeIndex: -1 // 滚动的index
},
methods: {
    startTimer() {
        this.timer = setInterval(this.playSlides, this.interval)
    },
    playSlides() {
        const items = this.items
        // 轮播滚动到最后一个就循环
        if (items.length && this.activeIndex < items.length - 1) {
          this.activeIndex++
        } else if (this.loop) {
          this.activeIndex = 0
        }
    },
},

这样在一加载完组件后,activeIndex开始递增,到了最后一个就重复,下面需要一个监听器,监听activeIndex的变化,然后去执行页面视图的变化。

watch: {
    autoplay(val) {
        if (val) {
          this.startTimer()
        }
    },
    activeIndex(activeIndex, oldIndex) {
    // 重新更新幻灯片的位置(主要函数)
     this.resetPositionItems(activeIndex, oldIndex)
    }
 },
 methods: {
     resetPositionItems(activeIndex, oldIndex) {
        this.items.forEach((item, index) => {
          item.initTranslate(index, activeIndex, oldIndex)
       })
    },
 }

子组件

name: 'NSlideItem',
data() {
  return {
    translate: 0,
    ready: false,
    animating: false
  }
},
methods: {
// 处理循环轮播
  processIndex(index, activeIndex, length) {
    // 如果是最后一张都第一张
    if (activeIndex === 0 && index === length - 1) {
      return -1;
      // 如果是第一张到对后一张
    } else if (activeIndex === length - 1 && index === 0) {
      return length;
    } else if (index < activeIndex - 1 && activeIndex - index >= length / 2) {
      return length + 1;
    } else if (index > activeIndex + 1 && index - activeIndex >= length / 2) {
      return -2;
    }
    return index;
  },
  initTranslate(index, activeIndex, oldIndex) {
        const length = this.$parent.items.length;

        if (index !== activeIndex && length > 2 && this.$parent.loop) {
          index = this.processIndex(index, activeIndex, length);
        }
        this.animating = activeIndex === index
        this.translate = this.calcTranslate(index, activeIndex)
        // 组件初始化完
        this.ready = true
      },
  // 计算位移的距离,重点就是这个函数
  calcTranslate(index, activeIndex) {
    // 获取父组件的宽度
    const distance = this.$parent.$el.offsetWidth
    // 可以仔细思考下这个计算
    return distance * (index - activeIndex)
      }
   }
},
computed: {
  translateStyle() {
  // this.translate变化时,返回对应的style
    return {
      transform: `translateX(${this.translate}px)`
    }
  }
},
created() {
  this.$parent && this.$parent.upDataItems()
}

这样轮播就实现了。测试一下

<template>
  <div style="width: 500px">
    <n-slide height="400px">
      <n-slide-item v-for="(item,index) of ['red','grey','black','orange']">
        <div class="item" :style="{height: '100%',background: item,color: '#ffffff',fontSize: '30px'}">
          {{index+1}}
        </div>
      </n-slide-item>
    </n-slide>
  </div>
</template>

063547eddb7626d336805a030917a41a.png

d3c6eb21037960cf8de47cfb03b0626b.png
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值