2020-10-12移动端触摸事件
2020-10-12 本文已影响0人
夏天的风2020
<template>
<scroll @scroll="scroll"
:listen-scroll="listenScroll"
:probe-type="probeType"
:data="data"
class="listview"
ref="listview">
<ul>
<li v-for="(group,index) in data"
class="list-group"
ref="listGroup"
:key="index">
<h2 class="list-group-title">{{group.title}}</h2>
<uL>
<li @click="selectItem(item)"
v-for="(item,index) in group.items"
:Key="index"
class="list-group-item">
<img class="avatar" v-lazy="item.avatar">
<span class="name">{{item.name}}</span>
</li>
</uL>
</li>
</ul>
<div class="list-shortcut"
@touchstart.stop.prevent="onShortcutTouchStart"
@touchmove.stop.prevent="onShortcutTouchMove"
@touchend.stop>
<ul>
<li v-for="(item, index) in shortcutList"
:key="index"
:data-index="index"
class="item"
:class="{'current':currentIndex===index}">{{item}}
</li>
</ul>
</div>
<div class="list-fixed"
ref="fixed"
v-show="fixedTitle">
<div class="fixed-title">{{fixedTitle}}----{{this.scrollY}} </div>
</div>
<div v-show="!data.length" class="loading-container">
<loading></loading>
</div>
</scroll>
</template>
<script type="text/ecmascript-6">
import Scroll from 'base/scroll/scroll'
import Loading from 'base/loading/loading'
import {getData} from 'common/js/dom'
const TITLE_HEIGHT = 30
const ANCHOR_HEIGHT = 18
export default {
props: {
data: {
type: Array,
default: []
}
},
computed: {
shortcutList() {
return this.data.map((group) => {
return group.title.substr(0, 1)
})
},
fixedTitle() {
if (this.scrollY > 0) {
return ''
}
return this.data[this.currentIndex] ? this.data[this.currentIndex].title : ''
}
},
data() {
return {
scrollY: -1,
currentIndex: 0, // 当前菜单栏在整个菜单中的下标index
diff: -1
}
},
created() {
// 为什么不在data中的创建touch?
// 在vue里面,不管是data还是props,都会被vue添加getter和setter,
// 也就是说它会观测data、props一级computed中值得变化,它会做一个监听,主要是跟dom做数据绑定,
// 而这里并不用观测touch中观测
this.probeType = 3
this.listenScroll = true
this.touch = {}
this.listHeight = []
},
methods: {
selectItem(item) {
this.$emit('select', item)
},
onShortcutTouchStart(e) {
console.log('eeeeeeeeeee')
console.log(e)
console.log(e.target)
let anchorIndex = getData(e.target, 'index')// 开始时触摸了第几个字符
let firstTouch = e.touches[0]
this.touch.y1 = firstTouch.pageY// 开始时触摸位置
this.touch.anchorIndex = anchorIndex
this._scrollTo(anchorIndex)
},
onShortcutTouchMove(e) {
let firstTouch = e.touches[0]
this.touch.y2 = firstTouch.pageY
let delta = (this.touch.y2 - this.touch.y1) / ANCHOR_HEIGHT | 0
let anchorIndex = parseInt(this.touch.anchorIndex) + delta
this._scrollTo(anchorIndex)
},
refresh() {
this.$refs.listview.refresh() // 刷线加载
},
scroll(pos) {
// console.log('scroll方法中滚动的距离----')
this.scrollY = pos.y
},
// 每个group的高度
_calculateHeight() {
this.listHeight = []
const list = this.$refs.listGroup
let height = 0
this.listHeight.push(height)
for (let i = 0; i < list.length; i++) {
let item = list[i]
height += item.clientHeight
this.listHeight.push(height)
}
},
// 侧边栏触摸触发
_scrollTo(index) {
console.log('开始滑动---')
console.log(index)
if (!index && index !== 0) {
console.log('开始滑动-1111111--')
return
}
console.log('开始滑动-22222222222--')
if (index < 0) {
index = 0
} else if (index > this.listHeight.length - 2) {
index = this.listHeight.length - 2
}
this.$refs.listview.scrollToElement(this.$refs.listGroup[index], 0)
this.scrollY = this.$refs.listview.scroll.y
console.log('开始滑动-3333--')
}
},
watch: {
data() {
setTimeout(() => {
// 数据变化获取不同字符组的高度
this._calculateHeight()
}, 20)
},
// newY和this.listHeight对比,看滚动到哪个区间
// 滚动的时候获取对应的currentIndex
scrollY(newY) {
console.log('监测滚动距离--scrollY')
console.log(newY)
const listHeight = this.listHeight
// 当滚动到顶部,继续向上滚动,newY>0
if (newY > 0) {
this.currentIndex = 0
return
}
// 在中间部分滚动
for (let i = 0; i < listHeight.length - 1; i++) {
let height1 = listHeight[i]
let height2 = listHeight[i + 1]
if (-newY >= height1 && -newY < height2) {
this.currentIndex = i
this.diff = height2 + newY
return
}
}
// 当滚动到底部,且-newY大于最后一个元素的上限
this.currentIndex = listHeight.length - 2
},
// 滚动差,做顶部上移效果
diff(newVal) {
// console.log('监测diff的变化')
// console.log(newVal)
let fixedTop = (newVal > 0 && newVal < TITLE_HEIGHT) ? newVal - TITLE_HEIGHT : 0
// console.log('fixedTop')
// console.log(fixedTop)
if (this.fixedTop === fixedTop) {
return
}
this.fixedTop = fixedTop
this.$refs.fixed.style.transform = `translate3d(0,${fixedTop}px,0)`
}
},
components: {
Scroll,
Loading
}
}
</script>
<style scoped lang="stylus" rel="stylesheet/stylus">
@import "~common/stylus/variable"
.listview
position: relative
width: 100%
height: 100%
overflow: hidden
background: $color-background
.list-group
padding-bottom: 30px
.list-group-title
height: 30px
line-height: 30px
padding-left: 20px
font-size: $font-size-small
color: $color-text-l
background: $color-highlight-background
.list-group-item
display: flex
align-items: center
padding: 20px 0 0 30px
.avatar
width: 50px
height: 50px
border-radius: 50%
.name
margin-left: 20px
color: $color-text-l
font-size: $font-size-medium
.list-shortcut
position: absolute
z-index: 30
right: 0
top: 50%
transform: translateY(-50%)
width: 20px
padding: 20px 0
border-radius: 10px
text-align: center
background: $color-background-d
font-family: Helvetica
.item
padding: 3px
line-height: 1
color: $color-text-l
font-size: $font-size-small
&.current
color: $color-theme
.list-fixed
position: absolute
top: 0
left: 0
width: 100%
.fixed-title
height: 30px
line-height: 30px
padding-left: 20px
font-size: $font-size-small
color: $color-text-l
//background: $color-highlight-background
background: red
.loading-container
position: absolute
width: 100%
top: 50%
transform: translateY(-50%)
</style>