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.”