效果图
一、安装引入better-scroll
npm install better-scroll --save
import BScroll from 'better-scroll'
二、获取右侧滑动的y轴坐标
data中的数据
scroll: '',
// 右侧滑动的y轴坐标(滑动过程中的实时变化)
scrollY: 0,
foodsScroll: '',
// 所有右侧分类li的top组成的数组
tops: [],
在methods定义初始化滚动
// 初始化滚动
initScroll() {
const container = this.$refs.container
this.scroll = new BScroll(container)
/* eslint-disable no-new */
new BScroll('.left_title', {
click: true
})
// 监听右侧列表
this.foodsScroll = new BScroll('.container', {
// 惯性滑动不会被触发
probeType: 2,
click: true
})
// 给右侧列表绑定scroll监听
this.foodsScroll.on('scroll', ({ x, y }) => {
// math.abs绝对值
this.scrollY = Math.abs(y)
console.log(x, y)
})
// 给右侧列表绑定滚动结束监听,滚动结束后改变左侧列表背景颜色
this.foodsScroll.on('scrollEnd', ({ x, y }) => {
this.scrollY = Math.abs(y)
})
},
三、初始化tops
// 初始化tops
_initTops() {
// 1.初始化tops
const tops = []
let top = 0
tops.push(top)
// 2.搜集
// 找到所有分类的li
const lis = this.$refs.foodsUI.getElementsByClassName('list')
Array.prototype.slice.call(lis).forEach(li => {
top += li.clientHeight
tops.push(top)
})
// 3。更新数据
this.tops = tops
console.log(this.tops)
},
四、计算当前分类的下标
computed: {
// 计算当前分类的下表
currentIndex() {
// 得到条件数据
const { scrollY, tops } = this
// 根据条件计算产出一个结果
const index = tops.findIndex((top, index) => {
return scrollY >= top && scrollY < tops[index + 1]
})
// 返会结果
return index
}
},
五、在mouted中调用
mounted() {
this.$nextTick(() => {
this.initScroll()
this._initTops()
})
}
全部代码
<template>
<div id="app">
<header>左右列表双向联动</header>
<div class="content">
<!-- 左侧列表 -->
<ul class="left_title" ref="left">
<li
class="title_item"
v-for="(item, index) in cateData"
:key="index"
:class="currentIndex === index ? 'active' : ''"
@click="change(index)"
>
{{ item.name }}
</li>
</ul>
<!-- 右侧内容区域 -->
<div class="right_content">
<div class="container" ref="container">
<div ref="foodsUI" class="foodsUI">
<div class="list">
<div class="name">健康蔬菜</div>
<ul>
<li>苹果</li>
<li>西红柿</li>
<li>番茄</li>
</ul>
</div>
.
.
.
.
.
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import BScroll from 'better-scroll'
export default {
data() {
return {
scroll: '',
// 右侧滑动的y轴坐标(滑动过程中的实时变化)
scrollY: 0,
foodsScroll: '',
// 所有右侧分类li的top组成的数组
tops: [],
cateData: [
{
name: '健康蔬菜'
},
{
name: '时令蔬菜'
},
{
name: '拨草'
},
{
name: '1'
},
{
name: '2'
},
{
name: '3'
},
{
name: '4'
},
{
name: '5'
},
{
name: '6'
}
]
}
},
methods: {
// 初始化滚动
initScroll() {
const container = this.$refs.container
this.scroll = new BScroll(container)
/* eslint-disable no-new */
new BScroll('.left_title', {
click: true
})
// 监听右侧列表
this.foodsScroll = new BScroll('.container', {
// 惯性滑动不会被触发
probeType: 2,
click: true
})
// 给右侧列表绑定scroll监听
this.foodsScroll.on('scroll', ({ x, y }) => {
// math.abs绝对值
this.scrollY = Math.abs(y)
console.log(x, y)
})
// 给右侧列表绑定滚动结束监听,滚动结束后改变左侧列表背景颜色
this.foodsScroll.on('scrollEnd', ({ x, y }) => {
this.scrollY = Math.abs(y)
})
},
// 初始化tops
_initTops() {
// 1.初始化tops
const tops = []
let top = 0
tops.push(top)
// 2.搜集
// 找到所有分类的li
const lis = this.$refs.foodsUI.getElementsByClassName('list')
Array.prototype.slice.call(lis).forEach(li => {
top += li.clientHeight
tops.push(top)
})
// 3。更新数据
this.tops = tops
console.log(this.tops)
},
// 点击左侧列表右侧滚动到相应位置
change(index) {
// 得到目标scrollY
const y = this.tops[index]
// 立即更新scrollY
this.scrollY = y
// 平滑滑动右侧列表
this.foodsScroll.scrollTo(0, -y, 300)
}
},
computed: {
// 计算当前分类的下表
currentIndex() {
// 得到条件数据
const { scrollY, tops } = this
// 根据条件计算产出一个结果
const index = tops.findIndex((top, index) => {
return scrollY >= top && scrollY < tops[index + 1]
})
// 返会结果
return index
}
},
mounted() {
this.$nextTick(() => {
this.initScroll()
this._initTops()
})
}
}
</script>
<style lang="less" scoped>
header {
height: 50px;
width: 100%;
background-color: green;
color: #fff;
font-size: 18px;
display: flex;
justify-content: center;
align-items: center;
}
.content {
display: flex;
.left_title {
flex: 1;
margin-right: 5px;
.title_item {
height: 35px;
width: 100%;
border: 1px solid #ccc;
display: flex;
justify-content: center;
align-items: center;
border-bottom: none;
&:last-child {
border-bottom: 1px solid #ccc;
}
}
}
.right_content {
flex: 3;
position: relative;
.name {
text-align: center;
padding: 20px;
}
.container {
overflow: hidden;
height: calc(100vh - 50px);
}
}
}
.active {
background-color: red;
color: #fff;
}
.list {
height: 200px;
border: 1px solid #ccc;
}
.foodsUI {
padding-bottom: 400px;
}
</style>