Element源码分析-Carousel走马灯

2,079 阅读2分钟

结构

以下的element官方标准的调用方式。其实调用起来很简单,初学vue就能看能看懂。

<el-carousel trigger="click" height="150px">
    <el-carousel-item v-for="item in 4" :key="item">
        <h3 class="small">{{ item }}</h3>
    </el-carousel-item>
</el-carousel>

main.vue

以下的main.vue源码

  <div
    :class="carouselClasses"
    @mouseenter.stop="handleMouseEnter"
    @mouseleave.stop="handleMouseLeave">
    <div
      class="el-carousel__container"
      :style="{ height: height }">
      <transition
        v-if="arrowDisplay"
        name="carousel-arrow-left">
        <button
          type="button"
          v-show="(arrow === 'always' || hover) && (loop || activeIndex > 0)"
          @mouseenter="handleButtonEnter('left')"
          @mouseleave="handleButtonLeave"
          @click.stop="throttledArrowClick(activeIndex - 1)"
          class="el-carousel__arrow el-carousel__arrow--left">
          <i class="el-icon-arrow-left"></i>
        </button>
      </transition>
      <transition
        v-if="arrowDisplay"
        name="carousel-arrow-right">
        <button
          type="button"
          v-show="(arrow === 'always' || hover) && (loop || activeIndex < items.length - 1)"
          @mouseenter="handleButtonEnter('right')"
          @mouseleave="handleButtonLeave"
          @click.stop="throttledArrowClick(activeIndex + 1)"
          class="el-carousel__arrow el-carousel__arrow--right">
          <i class="el-icon-arrow-right"></i>
        </button>
      </transition>
      <slot></slot>
    </div>
    <ul
      v-if="indicatorPosition !== 'none'"
      :class="indicatorsClasses">
      <li
        v-for="(item, index) in items"
        :key="index"
        :class="[
          'el-carousel__indicator',
          'el-carousel__indicator--' + direction,
          { 'is-active': index === activeIndex }]"
        @mouseenter="throttledIndicatorHover(index)"
        @click.stop="handleIndicatorClick(index)">
        <button class="el-carousel__button">
          <span v-if="hasLabel">{{ item.label }}</span>
        </button>
      </li>
    </ul>
  </div>

@event.stop 阻止事件冒泡

throttle 这个是 节流函数,在很多场景都需要用,element单独从npm引入包,我们可以点开学习一下,在之后的项目实战中,肯定会多遇到。其实要注意就是this的改变,callbak.apply(self, args);

以下的精简过后的源码

throttle: 节流函数 (下一次函数执行与上一次函数执行的时间间隔,控制在一定范围内)

function throttle(delay, callbak) {
	let timeoutID;
	let lastExec = 0; //上一次执行时间

	function wrapper() {
		const self = this;
		const args = arguments;
		const elapsed = Number(new Date()) - lastExec;  //执行函数与上一次的时间间隔
		
		function exec() {
			lastExec = Number(new Date());
			callbak.apply(self, args);
		}
		
		clearTimeout(timeoutID);
		
		if(elapsed > delay) {
			exec();
		}else{
			timeoutID = setTimeout(exec, delay- elapsed);
		}
	}
	return wrapper
}

item.vue

<div
    v-show="ready"
    class="el-carousel__item"
    :class="{
      'is-active': active,
      'el-carousel__item--card': $parent.type === 'card',
      'is-in-stage': inStage,
      'is-hover': hover,
      'is-animating': animating
    }"
    @click="handleItemClick"
    :style="itemStyle">
    <div
      v-if="$parent.type === 'card'"
      v-show="!active"
      class="el-carousel__mask">
    </div>
    <slot></slot>
  </div>

走马灯卡片切换的核心控制 itemStyle。其实实质就是通过css3 transform 平移实现的。 扩展一下,transform 代表“转变” 包含 rotate() 旋转 / skew() 倾斜 / scale() 缩放 / translate() 平移 这几种,另外每一种有X,Y之分 。 transition代表“过度效果” ,如果没有过度效果,平移就是尴尬的,看不出来效果。加了transition就不一样了。 transition: transform .4s ease-in-out;

事例:如果让某个元素做平移30个像素。

    transform: translateX(30px);
    -wekit-transform: translateX(30px);
    -moz-transform: translateX(30px);

后边也可以继续叠加属性 transform: translateX(30px) scale(0.83)

itemStyle() {
        const translateType = this.parentDirection === 'vertical' ? 'translateY' : 'translateX';
        const value = `${translateType}(${ this.translate }px) scale(${ this.scale })`;
        const style = {
          transform: value
        };
        return autoprefixer(style);
      }

代码不多就是根据方向判断,拼接平移的语句,autoprefixer是浏览器前缀,用于兼容浏览器的。

总结

1. 样式变量

:style="{height: height}"

:class="['class1','class2', {'is_active' ? true}]"

2. 节流和防抖函数

3. css3 transform transition