实现效果:左侧是导航,右边根据点击导航滚动到指定位置,右侧滚动到某个位置,左侧也要跟着变化。
使用的是原生微信小程序,使用了vant-weapp的侧边导航组件
<view class="content">
<scroll-view scroll-y class="left" show-scrollbar="{{false}}" enhanced>
<van-sidebar active-key="{{ activeSidebar }}" custom-class="custom-class">
<block wx:for="{{projects}}" wx:key="id">
<van-sidebar-item title="{{item.title}}" custom-class="custom-class-item" bind:click="onSidebarChange" />
</block>
</van-sidebar>
</scroll-view>
<scroll-view flex-able class="right" scroll-y bindscroll="onScroll" scroll-into-view="{{scrollIntoViewId}}" show-scrollbar="{{false}}" enhanced>
<block wx:for="{{projects}}" wx:key="id">
<view class="projects-content" id="projects-{{index}}">
{{item.title}}
...
</view>
</block>
</scroll-view>
</view>
data: {
activeSidebar: 0, // 左侧激活的项
scrollIntoViewId: '', // 右侧滚动到的视图id
contentHeights: [] as number[], // 存储每个分类内容的高度
projects:[...]
},
lifetimes: {
attached() {
this.calculateHeights()
},
},
methods: {
// 计算每个分类内容的高度,便于滚动时判断在哪个分类
calculateHeights() {
const query = this.createSelectorQuery();
let heights: number[] = [];
let totalHeight = 0;
// 遍历每个右侧分类内容,获取它们的高度
this.data.projects.forEach((_, index) => {
query.select(`#projects-${index}`).boundingClientRect((rect) => {
totalHeight += rect.height;
heights.push(totalHeight);
}).exec();
});
this.setData({
contentHeights: heights
});
},
// 右侧内容滚动时触发
onScroll(event: tapEventOption<any, { scrollTop: number }>) {
const scrollTop = event.detail.scrollTop;
const heights = this.data.contentHeights;
// 根据滚动高度计算当前应该激活的左侧项
for (let i = 0; i < heights.length; i++) {
if (scrollTop < heights[i]) {
this.setData({
activeSidebar: i
});
break;
}
}
},
// 左侧激活项变化时触发
onSidebarChange(event: tapEventOption<any, number>) {
const index = event.detail;
// 设置右侧内容滚动到相应的位置
this.setData({
activeSidebar: index,
scrollIntoViewId: `projects-${index}`
});
}
}
这是在子组件中,在attached中调用方法,因为我在父组件用了两个子组件切换展示,另一个不需要获取高度,只有attached中调用不报错,created中获取不到,ready中调用会在展示另一个子组件时报错,获取不到高度。
不过使用vant-weapp的侧边导航数据只能一层,要做点击后有子项需要展开的需要自己做
<scroll-view flex-able scroll-y class="left" show-scrollbar="{{false}}" enhanced>
<block wx:for="{{sidebar}}" wx:key="index">
<view class="one-level-item {{index === activeSidebar ? 'active' : ''}}" bind:tap="onSidebarChange" data-index="{{index}}">
{{item.name}}
<block wx:if="{{item.children.length}}">
<view class="triangle-down" wx:if="{{!item.expanded}}"></view>
<view class="triangle-up" wx:if="{{item.expanded}}"></view>
</block>
</view>
<block wx:if="{{item.expanded && item.children.length}}">
<block wx:for="{{item.children}}" wx:for-item="itm" wx:for-index="idx" wx:key="id">
<view class="two-level-item {{idx === activeSidebarItem ? 'active' : ''}}" bind:tap="onSidebarItem" data-idx="{{idx}}">{{itm.name}}</view>
</block>
</block>
</block>
</scroll-view>
用了滚动,如果里面有flex布局,scroll-view要加flex-able,不然里面的flex布局会失效
标签:index,滚动,侧边,heights,item,联动,导航,projects,wx From: https://blog.csdn.net/qq_51354326/article/details/142656322