需要实现的功能:
1 从首页跳进列表页,传入index参数,nav要根据index值滚动到对应的dom位置
2 点击 nav => 触发点击的dom滚动到顶部,(每次点击nav,data和title都需要初始化滚动位置)
3 data数据更新,title数据更新
4 点击 title => title 可以横向滚动,data数据也要滚动到与title对应的数据位置
npm:
npm install better-scroll --save
页面中引入:
import BScroll from ‘better-scroll’
页面布局
<template>
<div class="content">
<!-- 1. nav -->
<div class="nav_Warp">
<ul>
<li ref="nav_li" :class="{nav_active:nav_active == index}" @click="change_nav_active(index)" v-for="(item,index) in nav_list" :key="index">{{item}}</li>
</ul>
</div>
<!-- 2. title + data -->
<dataWarp :list="data_list"></dataWarp>
</div>
</template>
<style scoped lang="less">
.content{
display: flex;
.nav_Warp {
width: 20%;
background: #f4f4f4;
height: 95vh;
overflow: hidden;
ul {
overflow: scroll;
padding-bottom: 50px;
li {
padding-left: 10px;
border-left: 2px solid #f4f4f4;
text-align: left;
height: 50px;
line-height: 50px;
border-bottom: 1px solid #e8e9e8;
font-size: 12px;
}
.left_active{
border-left: 2px solid #3cb963;
font-size: 12px;
font-weight: bold;
color: #333333;
background: #fff;
}
}
}
}
</style>
// nav 初始化
<script>
import BScroll from 'better-scroll' // 引入BScroll
import dataWarp from './dataWarp ' // 引入 dataWarp组件
export default {
components: {
dataWarp,
},
data() {
return {
nav_list:[],// nav 列表数据
data_list:[],// data + title 商品数据
nav_active:0,// nav 高亮位置,默认第一索引0
}
},
mounted() {
// 初始化数据
this._initData();
// 如果首页跳转到列表页面 路由携带有参数,则200毫秒后触发nav滚动事件
if(this.$route.query.currentIndex){
setTimeout(()=>{
this.change_nav_active(this.$route.query.currentIndex)
},200)
}
},
methods: {
// 1. 初始化操作(数据和界面)
_initData() {
this.$nextTick(() => {
if (!this.leftScroll) {
this.leftScroll = new BScroll('.nav_Warp', {
probeType: 3,
click: true,
scrollY: true,
tap: true
});
} else {
this.leftScroll.refresh();//重新计算 better-scroll,当 DOM 结构发生变化的时候务必要调用确保滚动的效果正常。
}
});
// 1.1 这里发送axios请求获取nav data 列表 默认数据
this.nav_list = ['推荐','新鲜水果','新鲜蔬菜','方便速食','书房用品','厨房用品'];
this.data_list = [
{
title:"猜你喜欢",
list:['推荐','新鲜水果','新鲜蔬菜','方便速食','调味品','厨房用品','网红菜'],
},
{
title:"我的最爱",
list:['我的最爱'],
},
];
},
// 2. 点击nav,切换高亮,页面滚动到点击的dom位置
change_nav_active(i){
if(i != this.nav_active){
this.nav_active = i;//改变当前nav高亮
let nav_li = this.$refs.nav_li; //获取nav整个li数组
let el = nav_li[i]; //需要滚动到el位置
this.leftScroll.scrollToElement(el, 500);//开始滚动
// 2.1 根据nav点击项 发送axios请求data对应的数据,向子组件传值。
this.data_list = [
{
title:"猜你喜欢"+i,
list:['推荐'+i,'新鲜水果'+i,'新鲜蔬菜'+i,'方便速食'+i,'书房用品',],
},
{
title:"我的最爱"+i,
list:['推荐'+i,'新鲜水果'+i,'新鲜蔬菜'+i,'方便速食'+i],
},
];
}
},
},
}
</script>
dataWarp组件页面布局
<template>
<div class="Warp">
<!-- title -->
<div class="title_Wrap" ref="title_Wrap">
<ul ref="title_ulContent">
<li class="item" ref="title_item" v-for="(item,index) in list" :key="index" :class="{ac:title_active == index}" @click="change_title_active(index)">{{item.title}}</li>
</ul>
</div>
<!-- data -->
<div class="data_Warp">
<div class="content">
<div class="item" v-for="(item,index) in list" :key="index" ref="data_item">
<div class="title">{{item.title}}</div>
<ul>
<li ref="left_li" v-for="(val,i) in item.list" :key="i">{{val}}</li>
</ul>
</div>
</div>
</div>
</div>
</template>
<style scoped lang="less">
.Warp{
width: 80%;
.title_Wrap{
width: 100%;
white-space: nowrap;
background: #e8e9e8;
overflow: hidden;
ul{
display: flex;
li{
text-align: center;
height: 50px;
line-height: 50px;
font-size: 12px;
margin-right: 15px;
}
.ac{
color: #3cb963;
}
}
}
.data_Warp {
width: 100%;
height: 85vh;
overflow: hidden;
.item{
.title{
padding-left: 10px;
height: 50px;
line-height: 50px;
background: #f4f4f4;
}
ul {
overflow: scroll;
li {
padding-left: 10px;
border-left: 2px solid #f4f4f4;
text-align: left;
height: 100px;
line-height: 100px;
border-bottom: 1px solid #e8e9e8;
font-size: 12px;
}
}
}
}
}
</style>
// data title 逻辑部分
<script>
import BScroll from 'better-scroll'
export default{
props:{
// 接收父组件传过来的data数据
list: {
type: Array,
default: null
},
},
data(){
return{
title_active:0, // title 当前高亮,默认索引0
}
},
mounted(){
// 初始化更新滑动组件
this.$nextTick(() => {
this._initTitleScroll(); // 初始化title
this._initProductScroll(); // 初始化data
});
},
methods:{
// 1. title 滚动初始化
_initTitleScroll() {
let contentWrapperWidth = 120;//ul盒子宽度默认120
let el = this.$refs.title_item;//获取所有导航ul下的li
for (let i = 0; i < el.length; i++) {
contentWrapperWidth += el[i].clientWidth;//导航li宽度相加设置给ul
}
// 1.1给ul设置宽度,保证可以横向滚动
this.$refs.title_ulContent.style.width = contentWrapperWidth + 'px';//给ul设置宽度
if (!this.titleScroll) {
this.titleScroll = new BScroll('.title_Wrap', {
probeType: 3,
startX: 0,
click: true,
scrollX: true,
});
} else {
this.titleScroll.refresh();//重新计算 better-scroll,当 DOM 结构发生变化的时候务必要调用确保滚动的效果正常。
}
},
// 2. 商品滚动初始化
_initProductScroll() {
this.$nextTick(() => {
if (!this.rightScroll) {
this.rightScroll = new BScroll('.data_Warp', {
probeType: 3,
click: true
});
} else {
this.rightScroll.refresh();//重新计算 better-scroll,当 DOM 结构发生变化的时候务必要调用确保滚动的效果正常。
// 2.1 进入默认商品列表滚到顶部
this.rightScroll.scrollToElement(this.$refs.right_item[0], 10, 0, 0);//滚动到dom位置
// 2.2 title默认索引位置0
this.title_active = 0;
}
});
},
// 3. title 切换
change_title_active(i){
this.title_active = i;//高亮显示
// 3.1 商品列表滚动
let data_item = this.$refs.data_item; //获取data的整个item数组
let el = data_item[i]; //需要滚动到el位置
this.rightScroll.scrollToElement(el, 500);//开始滚动
// 3.2 title 滚动
let els = this.$refs.title_item[i];//获取所有title的item
this.titleScroll.scrollToElement(els, 500);//开始滚动
},
},
watch: {
//list数据改变需要重新初始化组件
list() {
this.$nextTick(() => {
this._initTitleScroll();
this._initProductScroll();
});
}
},
}
</script>
better-scroll:参数说明:
probeType
可选值:1、2、3
作用:有时候我们需要知道滚动的位置。
当 probeType 为 1 的时候,会非实时(屏幕滑动超过一定时间后)派发scroll 事件;
当 probeType 为 2 的时候,会在屏幕滑动的过程中实时的派发 scroll 事件;
当 probeType 为 3 的时候,不仅在屏幕滑动的过程中,而且在 momentum 滚动动画运行过程中实时派发 scroll 事件。
如果没有设置该值,其默认值为 0,即不派发 scroll 事件。
click
默认值:false
作用:better-scroll 默认会阻止浏览器的原生 click 事件。当设置为 true,
better-scroll 会派发一个 click 事件,我们会给派发的 event 参数加一个私有属性 _constructed,值为 true。
scrollX
默认值: false
作用:当设置为 true 的时候,可以开启横向滚动。
备注:当设置 eventPassthrough 为 ‘horizontal’ 的时候,该配置无效。
scrollY
默认值:true
作用:当设置为 true 的时候,可以开启纵向滚动。
备注:当设置 eventPassthrough 为 ‘vertical’ 的时候,该配置无效。
tap
默认值:false
作用:因为 better-scroll 会阻止原生的 click 事件,我们可以设置 tap 为 true,它会在区域被点击的时候派发一个 tap 事件,你可以像监听原生事件那样去监听它,如 element.addEventListener(‘tap’, doSomething, false);。
如果 tap 设置为字符串, 那么这个字符串就作为自定义事件名称。如 tap: ‘myCustomTapEvent’。
refresh()
作用:重新计算 better-scroll,当 DOM 结构发生变化的时候务必要调用确保滚动的效果正常。
来源:CSDN
作者:934353403
链接:https://blog.csdn.net/qq_40745143/article/details/103476978