左右联动的时候右边高亮显示的对不上
来源:5-9 listview 基础组件的开发和应用-滚动固定标题实现(上)
小徐子是我
2019-02-26
在这里输入代码<template>
<scroll
class="listview"
ref="listview"
@scroll="scroll"
:listen-scroll="listenScroll"
:probe-type = "probeType"
>
<ul>
<li v-for="(group, index) in data" :key="index" ref="listgroup" class="list-group">
<!-- 热门 -->
<h2 class="list-group-title">{{group.title}}</h2>
<ul>
<li v-for="(item, index) in group.items" class="list-group-item" :key="index">
<img class="avatar" v-lazy="item.avatar" alt>
<span class="name">{{item.name}}</span>
</li>
</ul>
</li>
</ul>
<div class="list-shortcut" >
<ul>
<!-- 右侧字母 -->
<li v-for="(item, index) in shortcutList" @touchstart.stop.prevent="onShortcutTouchStart" @touchmove.stop.prevent="onShortcutTouchMove"
:data-index="index"
:key="index"
class="item"
:class="{'current' : currentIndex === index}">{{item}}</li>
</ul>
</div>
<!-- <div class="list-fixed">
<div class="fixed-title">{{fixedTitle}}</div>
</div> -->
<div class="loading-container" v-show="!data.length">
<loading></loading>
</div>
</scroll>
</template>
<script type="text/ecmascript-6">
import Loading from "base/loading/loading";
import Scroll from "base/scroll/scroll";
import {getData} from "common/js/dom"
const ANCHOR_HEIGHT = 18
export default {
props: {
// 已经在父组件处理好的数据
data: {
type: Array,
default: [],
}
},
computed: {
// 右侧字母
shortcutList() {
// data的每个元素
return this.data.map(group => {
// 选择一个字母 热
return group.title.substr(0, 1);
});
},
fixedTitle() {
// console.log(this.scrolly)
if (this.scrolly > 0) {
return "";
}
// return this.data[this.currentIndex] ?
}
},
created() {
this.probeType = 3,
this.touch = {},
this.listenScroll = true,
this.listHeight = []
},
data() {
return {
scrollY: -1,
currentIndex: 0,
diff: -1
};
},
methods: {
onShortcutTouchStart(e) {
// 获取当前点击的index
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) {
// 离开的位置
// 减去第一次触碰的位置然后除以元素高18px就可以拿到有几个元素
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)
},
scroll(pos) {
this.scrollY = pos.y
},
_scrollTo(index) {
console.log(index)
if (!index && index !== 0) {
return
}
// 如果超出顶部
if(index < 0) {
alert('超出顶部')
index = 0
// 或者超出底部
} else if (index > this.listHeight.length -2) {
index = this.listHeight.length -2
}
this.$refs.listview.scrollToElement(this.$refs.listgroup[index], 0)
// 获取y轴向上的距离
// this.scrollY = this.$refs.listview.scroll.y
this.scrollY = this.listHeight[index]
},
_calculateHeight() {
this.listHeight = []
const list = this.$refs.listgroup
let height = 0
for (let i = 0; i < list.length; i++) {
let item = list[i]
height += item.clientHeight
this.listHeight.push(height)
}
}
},
watch: {
data() {
setTimeout(() => {
this._calculateHeight()
},20)
},
scrollY(newY) {
// 向上滑动 newy 是负值
// console.log(newY)
// console.log(this.data)
// 获取所有的高度
const listHeight = this.listHeight
// 如果大于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]
console.log('height1', height1)
console.log('height2', height2)
console.log('i', i)
if(-newY >= height1 && -newY < height2) {
this.currentIndex = i
// console.log(this.currentIndex)
return
}
}
this.currentIndex = listHeight.length -2
}
},
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
.loading-container
position absolute
width 100%
top 50%
transform translateY(-50%)
</style>
写回答
1回答
-
ustbhuangyi
2019-02-27
建议仔细对比我的 GitHub 源码
可以考虑直接用 cube-ui 的 IndexList 组件:https://didi.github.io/cube-ui/#/zh-CN/docs/index-list
可以参考 IndexList 组件的实现:https://github.com/didi/cube-ui/blob/dev/src/components/index-list/index-list.vue
0232019-03-05
相似问题