- 左右两侧分别使用scroll-view包裹,保证滑动互不干扰,如果使用pageScroll事件监听,左右会有干扰
使用到的标签
<scroll-view
class="categories_view"
scroll-y
:scroll-top="cateTop"
>
- 计算右侧、左侧 每个分类的高度、距离顶部的距离、和窗口的大小
使用到的方法
this.data.forEach((item) => {
uni.createSelectorQuery().select(`#title_view_${item.id}`).boundingClientRect((rect) => {
item.offsetTop = rect.top //左侧grid距离顶部的距离
item.height = rect.height //左侧grid的高度
item.index = rect.dataset.cateIndex //左侧grid的顺序
}).exec()
this.data.forEach((item, index) => {
uni.createSelectorQuery().select(`.category_${index}`).boundingClientRect((rect) => {
item.cateOffsetTop = rect.top //右侧分类距离顶部的距离
}).exec()
})
uni.getSystemInfo({
success(info) {
windowsHeight = info.windowHeight //窗口的大小
},
})
- 监听右侧滚动事件和左侧点击事件
//左侧点击事件
@click="titleClickHandler"
titleClickHandler(event) {
this.cateActiveId = +event.currentTarget.dataset.cate //左侧点击元素的id
this.cateActiveIndex = +event.currentTarget.dataset.cateIndex //左侧点击元素的索引
this.top = this.data[this.cateActiveIndex].offsetTop //左侧点击元素对应的右侧元素滚动的距离
},
//右侧滚动事件
<scroll-view
class="types_view"
scroll-y
:scroll-top="top" //对应上面的top
scroll-with-animation
@scroll="onscroll"
>
onscroll(e) {
let target = this.data[0]
for (const item of this.data) {
//滚动到某个元素中间的位置, -8是对应的margin-bottom
if (e.detail.scrollTop > item.offsetTop - 8 && e.detail.scrollTop < item.offsetTop - 8 + item.height) {
target = item
}
//反向回显左侧的分类
this.cateActiveId = target.id
this.cateActiveIndex = target.index
//左侧超出一页,右侧滑动到左侧超出一页的位置,右侧触发滚动
if (this.data[this.cateActiveIndex].cateOffsetTop > windowsHeight) {
this.cateTop = this.data[this.cateActiveIndex].cateOffsetTop
} else {
this.cateTop = -this.data[this.cateActiveIndex].cateOffsetTop
}
}
}
- 最后一个grid要占满整个页面
getPaddingBottom() {
return `padding-bottom: calc(100vh - ${this.data[this.data.length - 1].height}px)`
},
- 代码实现
<template>
<view class="projects_view">
<scroll-view
class="categories_view"
scroll-y
:scroll-top="cateTop"
>
<view
v-for="(item, index) in data"
:key="item.id"
:class="[
{
title_active: item.id === cateActiveId,
title_top_active: index === cateActiveIndex - 1,
title_bottom_active: index === cateActiveIndex + 1,
},
'category_' + index]"
class="title_view"
:data-cate="item.id"
:data-cate-index="index"
@click="titleClickHandler"
>
{{ item.name + index }}
</view>
</scroll-view>
<scroll-view
class="types_view"
scroll-y
:scroll-top="top"
scroll-with-animation
@scroll="onscroll"
>
<view
v-for="(item, index) in data"
:id="'title_view_'+ item.id"
:key="item.id"
:data-cate-index="index"
:style="index === data.length - 1 ? getPaddingBottom : ''"
>
<view
:data-cate-index="index"
class="title"
>
{{ item.name }} {{ index }}
</view>
<u-grid
:col="2"
>
<u-grid-item
v-for="c in item.children"
:key="c.id"
:name="c.id"
@click="gridClickHandler"
>
<image
class="badge_icon"
src="https://cdn.uviewui.com/uview/example/button.png"
>
{{ c.icon }}
</image>
<view class="grid-text">{{ c.name }}{{ c.id }}</view>
</u-grid-item>
</u-grid>
</view>
</scroll-view>
</view>
</template>
<script>
let windowsHeight
export default {
data() {
return {
cateActiveId: null,
cateActiveIndex: 0,
top: 0,
cateTop: 0,
data: [
{
name: '工程类',
id: 1,
children: [{
name: '一级建造师',
id: 3,
},
{
name: '一级建造师',
id: 4,
},
{
name: '一级建造师',
id: 5,
},
{
name: '一级建造师',
id: 7,
},
{
name: '一级建造师',
id: 8,
},
{
name: '一级建造师',
id: '9',
},
{
name: '一级建造师',
id: 10,
},
{
name: '一级建造师',
id: 11,
},
{
name: '一级建造师',
id: 12,
},
{
name: '一级建造师',
id: 20,
},
{
name: '一级建造师',
id: 21,
},
{
name: '一级建造师',
id: 22,
},
],
},
{
name: '工程类',
id: 13,
children: [{
name: '一级建造师',
id: 27,
},
{
name: '一级建造师',
id: 42,
},
{
name: '一级建造师',
id: 43,
}],
},
{
name: '工程类',
id: 14,
children: [{
name: '一级建造师',
id: 23,
}],
},
{
name: '工程类',
id: 15,
children: [{
name: '一级建造师',
id: 24,
}],
},
{
name: '工程类',
id: 16,
children: [{
name: '一级建造师',
id: 25,
}],
},
{
name: '工程类',
id: 17,
children: [{
name: '一级建造师',
id: 26,
}],
},
{
name: '工程类',
id: 18,
children: [{
name: '一级建造师',
id: 28,
}],
},
{
name: 'kk',
id: 19,
children: [{
name: '一级建造师',
id: 29,
}],
},
{
name: 'kk',
id: 30,
children: [{
name: '一级建造师',
id: 31,
}],
},
{
name: 'kk',
id: 32,
children: [{
name: '一级建造师',
id: 33,
}],
},
{
name: 'kk',
id: 34,
children: [{
name: '一级建造师',
id: 35,
}],
},
{
name: 'kk',
id: 36,
children: [{
name: '一级建造师',
id: 37,
}],
},
{
name: 'kk',
id: 38,
children: [{
name: '一级建造师',
id: 39,
}],
},
{
name: 'kk',
id: 40,
children: [{
name: '一级建造师',
id: 41,
}],
},
],
}
},
computed: {
getPaddingBottom() {
return `padding-bottom: calc(100vh - ${this.data[this.data.length - 1].height}px)`
},
},
methods: {
getGridItemOffsetTop() {
this.data.forEach((item) => {
uni.createSelectorQuery().select(`#title_view_${item.id}`).boundingClientRect((rect) => {
item.offsetTop = rect.top
item.height = rect.height
item.index = rect.dataset.cateIndex
}).exec()
})
this.data.forEach((item, index) => {
uni.createSelectorQuery().select(`.category_${index}`).boundingClientRect((rect) => {
item.cateOffsetTop = rect.top
}).exec()
})
uni.getSystemInfo({
success(info) {
windowsHeight = info.windowHeight
},
})
},
onscroll(e) {
let target = this.data[0]
for (const item of this.data) {
if (e.detail.scrollTop > item.offsetTop - 8 && e.detail.scrollTop < item.offsetTop - 8 + item.height) {
target = item
}
this.cateActiveId = target.id
this.cateActiveIndex = target.index
if (this.data[this.cateActiveIndex].cateOffsetTop > windowsHeight) {
this.cateTop = this.data[this.cateActiveIndex].cateOffsetTop
} else {
this.cateTop = -this.data[this.cateActiveIndex].cateOffsetTop
}
}
},
gridClickHandler(index) {
this.$Router.push({
path: '/pages/home/index',
})
},
titleClickHandler(event) {
this.cateActiveId = +event.currentTarget.dataset.cate
this.cateActiveIndex = +event.currentTarget.dataset.cateIndex
this.top = this.data[this.cateActiveIndex].offsetTop
},
},
onReady() {
// Todo: 获取data
// 返回data的第一个id
this.cateActiveId = 1
this.getGridItemOffsetTop()
},
}
</script>
<style scoped lang="scss">
:deep(.u-grid) {
padding-left: 10px;
width: 100%;
}
:deep(.u-grid-item) {
background-color: #FFFFFF !important;
width: calc(50% - 8px) !important;
border-radius: 10px;
padding: 15px 0;
margin-right: 8px;
margin-bottom: 8px;
}
.badge_icon {
width: 40px;
height: 40px;
}
.grid-text {
font-size: 12px;
margin-top: 10px;
color: #666666;
}
.projects_view {
display: flex;
width: 100%;
height: 100vh;
}
.title {
background-color: #F7F7F7;
padding: 21px;
color: #999999;
}
.title_view {
padding: 21px;
color: #999999;
background-color: #FFFFFF;
}
.title_top_active {
border-bottom-right-radius: 10px;
}
.title_bottom_active {
border-top-right-radius: 10px;
}
.title_active {
background-color: #F7F7F7;
color: #3C8AFD;
}
.categories_view {
font-size: 16px;
background-color: #F7F7F7;
color: #999999;
min-width: 100px;
flex: 1;
}
.types_view {
flex: 3;
background-color: #F7F7F7;
}
</style>
标签:uniapp,界面,name,建造师,分类,item,data,id,一级
From: https://www.cnblogs.com/tangshidedabenniao/p/17638969.html