Small knowledge, big challenge! This article is participating in the creation activity of “Essential Tips for Programmers”

TIP 👉 The enemy should not be resolved knot, each look back. Ming Feng Menglong, Ancient and Modern Novels

preface

In our daily project development, we will involve the function of scroll selection when we do mobile terminal, so we encapsulate this scroll selection component.

Scroll selection component

attribute

1. value
  • The current selected value can be the option object in Options or value of options
  • Value types: string (option value), numeric (option value), or object (option object)
2. options
  • Options array
  • The value type is array. Example: [{value: ’01’, text: ‘male ‘}, {value: ’02’, text:’ female ‘}]

The event

1. change
  • The event that fires when a value changes
  • Parameters:
    • CurrentOption: the currently selected option object, for example: {value: ’01’, text: ‘male ‘}
2. input
  • The event that fires when a value changes
  • Parameters:
    • Value: value of the currently selected option, example: ’01’

Implement scrollSelect. Vue

<template>
  <div>
      <div class="f-flex f-flext scroll-select" @touchmove.prevent="" @mousewheel.prevent="">
        <div class="f-flex1 f-tac f-oh">
          <ul :class="{'dragging': dragging}" @touchstart.stop="handleTouchStart($event)" @mousedown.stop="handleTouchStart($event)" :style="{'transform' : 'translate3d(0,' + translateY + 'px, 0)'}">
            <li ref="li"></li>
            <li class="f-toe" v-for="(item, index) in options" :key="item.value" :class="{ 'current': currentOption ? item.value === currentOption.value : false, 'node1': Math.abs(index - currentIndex) == 1, 'node2': Math.abs(index - currentIndex) == 2, 'node3': Math.abs(index - currentIndex) >= 3 }">{{item.text}}</li>
            <li></li>
            <li></li>
            <li></li>
          </ul>
        </div>
        <div class="net-monitor"></div>
      </div>
  </div>
</template>
<script>
export default {
  name: 'ScrollSelect'.props: {
    // The current selected value
    value: [String.Number.Object]./** * Selection list array * Example objects in array: {value: '01', text: 'male '} * value: value * text: displayed text **/
    options: {
      type: Array.default: () = > []
    }
  },
  data () {
    return {
      // Index position of the currently selected value
      currentIndex: 0.// Options for the currently selected value, for example: {value: '01', text: 'male '}
      currentOption: {},
      dragging: false.distanceY: 0.translateY: 0}},watch: {
    value (val) {
      this.initValue(val)
      this.initTranslateY()
    },
    options (val) {
      if (val && val instanceof Array) {
        this.initValue(this.currentOption)
        this.initTranslateY()
      }
    }
  },
  created () {
    this.initValue(this.value)
  },
  mounted () {
    this.initTranslateY()
    if (typeof this.value === 'string' || typeof this.value === 'number') {
      this.$emit('change'.this.currentOption)
    }
  },
  beforeDestroy () {
    document.removeEventListener('touchmove'.this.handleTouchMove)
    document.removeEventListener('touchend'.this.handleTouchEnd)
    document.removeEventListener('mousemove'.this.handleTouchMove)
    document.removeEventListener('mouseup'.this.handleTouchEnd)
  },
  methods: {
    initValue (value) {
      let currentIndex = 0
      let currentOption = this.options.length > 0 ? this.options[0] : null
      if(value ! = =null && typeofvalue ! = ='undefined') {
        this.options.forEach((val, idx) = > {
          if (typeof value === 'string' || typeof value === 'number') {
            if (val.value === value) {
              currentOption = val
              currentIndex = idx
            }
          } else if (val.value === value.value) {
            currentOption = val
            currentIndex = idx
          }
        })
      }
      this.currentIndex = currentIndex
      this.currentOption = currentOption
    },
    initTranslateY () {
      let clientHeight = this.$refs.li.offsetHeight
      this.translateY = -clientHeight * this.currentIndex
    },
    setPage () {
      let clientHeight = this.$refs.li.offsetHeight
      let total = this.options.length
      let goPage = Math.round((this.translateY / clientHeight).toFixed(1))
      if (goPage > 0) {
        goPage = 0
      }
      goPage = total - 1> =Math.abs(goPage) ? goPage : -(total - 1)
      let index = Math.abs(goPage)
      this.currentOption = this.options[index]
      this.currentIndex = index
      this.translateY = goPage * clientHeight
      this.$emit('change'.this.currentOption)
      this.$emit('input'.this.currentOption.value)
    },
    getPageY (e) {
      return e.changedTouches ? e.changedTouches[0] ['pageY'] : e['pageY']
    },
    handleTouchStart (e) {
      this.distanceY = 0
      this.startY = this.getPageY(e)
      this.startTranslateY = this.translateY
      this.dragging = true
      document.addEventListener('touchmove'.this.handleTouchMove, false)
      document.addEventListener('touchend'.this.handleTouchEnd, false)
      document.addEventListener('mousemove'.this.handleTouchMove, false)
      document.addEventListener('mouseup'.this.handleTouchEnd, false)
    },
    handleTouchMove (e) {
      this.distanceY = this.getPageY(e) - this.startY
      this.translateY = this.startTranslateY + this.distanceY
    },
    handleTouchEnd (e) {
      this.dragging = false
      this.setPage()
      document.removeEventListener('touchmove'.this.handleTouchMove)
      document.removeEventListener('touchend'.this.handleTouchEnd)
      document.removeEventListener('mousemove'.this.handleTouchMove)
      document.removeEventListener('mouseup'.this.handleTouchEnd)
    },
    // Get the default value
    getDefaultValue (value) {
      if (this.options.length > 0) {
        return this.options[0]}else {
        return{}}}}}</script>
<style lang="scss" scoped>
.scroll-select {
  position: relative;
  width: 100%;
  margin: 0 auto;
  background: transparent;
  height: 350px;
  overflow: hidden;
  color: #2D3859;
  ul {
    transition: all .4s ease;
    padding-top: 27px;
    &.dragging {
      transition: none;
    }
    li {
      line-height: 98px;
      height: 98px;
      font-size: 36px;
      text-align: center;
      color: #a8a8a8;
      transition:.3s ease;
      &.current {
        font-size: 40px;
        color: # 333333;
      }
      &.node1 {
        font-size: 36px;
        opacity:.7;
      }
      &.node2 {
        font-size: 32px;
        opacity:.5;
      }
      &.node3 {
        font-size: 28px;
        opacity:.3; }}}}.net-monitor {
  width: 100%;
  height: 94px;
  border: 1px solid $base-color;
  border-left-width: 0;
  border-right-width: 0;
  @include base-border-color(.5);
  position: absolute;
  bottom: 125px;
  @include base-background-color(.1);
  z-index: -1;
}
.f-toe {
  overflow: hidden;
  word-wrap: normal;
  white-space: nowrap;
  text-overflow: ellipsis;
}
</style>
Copy the code

index.js

/** * Scroll to select component */
import ScrollSelect from './ScrollSelect.vue'
export default ScrollSelect
Copy the code

“Feel free to discuss in the comments section.”

Hope to finish watching friends can give a thumbs-up, encourage once