首页 > 其他分享 >uniapp 分类界面实现

uniapp 分类界面实现

时间:2023-08-17 22:33:16浏览次数:46  
标签:uniapp 界面 name 建造师 分类 item data id 一级

image

  1. 左右两侧分别使用scroll-view包裹,保证滑动互不干扰,如果使用pageScroll事件监听,左右会有干扰
    使用到的标签
<scroll-view
      class="categories_view"
      scroll-y
      :scroll-top="cateTop"
    >
  1. 计算右侧、左侧 每个分类的高度、距离顶部的距离、和窗口的大小
    使用到的方法
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 //窗口的大小
        },
      })
  1. 监听右侧滚动事件和左侧点击事件
//左侧点击事件
@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
        }
      }
    }
  1. 最后一个grid要占满整个页面
getPaddingBottom() {
      return `padding-bottom: calc(100vh - ${this.data[this.data.length - 1].height}px)`
    },
  1. 代码实现
<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

相关文章