用Element-Ui封装一个滑动组件


基于Element-Ui的“Slider滑块”组件封装一个前端滑动滑动验证组件

  • 主要用于登录验证
  • 纯前端验证(滑着过瘾)目前无法与后端进行校验
  • 封装还可以优化
  • 直接看代码吧

    slider组件

    // slider/index.vue'
    <template>
      <div class="bar" ref="bar">
        <el-slider
          class="slider"
          ref="slider"
          v-model="value"
          :show-tooltip="false"
          @change="sliderChange"
          :disabled="sliderDisabled"
        ></el-slider>
        <div class="slider-text-before" ref="barText">
          <div :class="noReset?'run run-no-slider':'run'" v-if="!isSuccess">拖动滑块验证</div>
          <span v-else style="color:#fff;">验证通过</span>
        </div>
      </div>
    </template>
    <script>
    export default {
      name: "slider",
      props: {
        reset: {
          type: Boolean,
          default: false
        },
        noReset: {
          type: Boolean,
          default: false,
        }
      },
      data() {
        return {
          value: 0,
          isSuccess: false,
          sliderDisabled: false
        };
      },
      watch: {
        reset: function(val) {
          if (val) {
            this.sliderReset();
          }
        },
        noReset(val){
          if(val){
            this.$refs.bar.classList.add("no-slider")
          }else{
            this.$refs.bar.classList.remove("no-slider")
          }
        },
        value(val){
          this.$emit("value",val)
        }
      },
      created() {
        },
      mounted() {
        console.log(this.$refs.slider.$refs.button1.$refs.button)
    
    
        // this.$refs.slider.$refs.button1.$refs.button.style = ""
        this.$refs.slider.$refs.button1.$refs.button.lastChild.innerHTML =
          "<i class='el-icon-d-arrow-right icon-arrow-right'></i>";
    
      },
      methods: {
        sliderChange(val) {
          if (val === 100) {
            this.sliderSucceed();
          } else {
            this.sliderReset();
          }
        },
        sliderSucceed() {
          this.isSuccess = true;
          this.$refs.slider.$refs.button1.$refs.button.lastChild.innerHTML =
            "<i class='el-icon-success icon-success'></i>";
          this.sliderDisabled = true;
          this.$emit("success", true);
        },
        sliderReset() {
          this.isSuccess = false;
          this.value = 0;
          this.sliderDisabled = false;
          this.$emit("update:reset", false);
          this.$refs.slider.$refs.button1.$refs.button.lastChild.innerHTML =
            "<i class='el-icon-d-arrow-right icon-arrow-right'></i>";
        }
      }
    };
    </script>
    <style lang="scss" scoped>
    $color: #67c23a;
    // $color: #409EFF;
    $slider_button_width: 60px;
    $slider_button_height: 40px;
    .bar {
      position: relative;
      width: 100%;
      background-color: #e4e7ed;
      border-radius: 3px;
      .slider-text-before {
        position: absolute;
        left: 50%;
        top: 50%;
        transform: translate(-50%, -50%);
        font-size: 16px;
        letter-spacing: 2px;
        user-select: none;
        .run {
          padding: 0 30px;
          color: transparent;
          -moz-user-select: none;
          -webkit-user-select: none;
          user-select: none;
          -o-user-select: none;
          -ms-user-select: none;
          background: -webkit-gradient(
            linear,
            left top,
            right top,
            color-stop(0, #333),
            color-stop(0.3, #333),
            color-stop(0.5, #fff),
            color-stop(0.7, #333),
            color-stop(1, #333)
          );
          -webkit-background-clip: text;
          -webkit-text-fill-color: transparent;
          -webkit-text-size-adjust: none;
          -webkit-animation: slidetounlock 3s infinite;
          animation: slidetounlock 3s infinite;
        }
        .run-no-slider{
          background: -webkit-gradient(
            linear,
            left top,
            right top,
            color-stop(0, #F56C6C),
            color-stop(0.3, #F56C6C),
            color-stop(0.5, #fff),
            color-stop(0.7, #F56C6C),
            color-stop(1, #F56C6C)
          );
          -webkit-background-clip: text;
          -webkit-text-fill-color: transparent;
          -webkit-text-size-adjust: none;
          -webkit-animation: slidetounlock 3s infinite;
          animation: slidetounlock 3s infinite;
        }
      }
      .slider-text-after {
        position: absolute;
        left: 50%;
        top: 50%;
        transform: translate(-50%, -50%);
        z-index: 10;
        color: #fff;
      }
      .slider {
        width: calc(100% - #{$slider_button_width});
        /deep/.el-slider__runway {
          margin: 0;
        }
        /deep/.el-slider__bar {
          height: 40px;
          background-color: $color;
          border-top-left-radius: 0px;
          border-bottom-left-radius: 0px;
        }
        /deep/.el-slider__runway {
          height: 40px;
        }
        /deep/.el-slider__button-wrapper {
          top: 0;
          width: $slider_button_width;
          height: 40px;
          margin-left: ($slider_button_width/2);
          :hover {
            transform: none;
          }
        }
        /deep/.el-slider__button {
          width: $slider_button_width;
          height: 40px;
          border-radius: 0;
          border-color: #dcdfe6;
          :hover {
            transform: none;
          }
        }
        /deep/.el-slider__button.dragging,
        .el-slider__button.hover,
        .el-slider__button:hover {
          -webkit-transform: none !important;
          transform: none !important;
        }
        /deep/.el-slider__runway.disabled .el-slider__button:hover {
          cursor: grab !important;
        }
        /deep/.icon-arrow-right {
          line-height: ($slider_button_height - 4px);
          font-size: 18px;
          color: #4c4c4c;
        }
        /deep/.icon-success {
          line-height: ($slider_button_height - 4px);
          font-size: 20px;
          color: $color;
        }
      }
    }
    @-webkit-keyframes slidetounlock {
      from {
        background-position: -70px 100%;
      }
      to {
        background-position: 80px 0;
      }
    }
    .no-slider{
      animation: shake 800ms ease-in-out;
    }
    
    @keyframes shake {
        10%, 90% { transform: translate3d(-1px, 0, 0); }
        20%, 80% { transform: translate3d(+2px, 0, 0); }
        30%, 70% { transform: translate3d(-4px, 0, 0); }
        40%, 60% { transform: translate3d(+4px, 0, 0); }
        50% { transform: translate3d(-4px, 0, 0); }
    }
    </style>

    使用

    // 引入
    import slider from './slider'
    
    // 使用
     <slider v-bind:reset.sync="isResetSlider" :noReset="isNoReset" @value="sliderValue" @success="sliderSuccess"></slider>
    
    components:{
      slider
    },
    data() {
      return {
        isResetSlider: false,
        isSeccess: false,
        sliderVal: "",
        isNoReset: false
      };
    }
    
    methods: {
      // 滑动验证
      sliderSuccess(val){
        this.isSeccess = val
      },
      sliderValue(val){
        this.sliderVal = val
      },
      submitForm() {
        if(this.sliderVal == 0){
          this.isNoReset = true
          setTimeout(() => {
            this.isNoReset = false
          }, 900);
          return
        }
        if(this.isSeccess){
          console.log("submit");
          this.isResetSlider = true
          this.isSeccess = false
        }else{
          console.log("请滑动滑块验证");
        }
      }
    }
    效果截图
  • 滑动验证-未滑动

滑动验证-未滑动
滑动验证-未滑动

  • 滑动验证-滑动中

滑动验证-滑动中
滑动验证-滑动中

  • 滑动验证-滑动成功

滑动验证-滑动成功
滑动验证-滑动成功

  • 滑动验证GIF

滑动验证GIF
滑动验证GIF


  目录