uniapp上实现左右关联滚动

news2025/1/18 4:49:12

先看效果:

在这里插入图片描述

代码:

<template>
  <view class="container">
    <!-- 左侧fixed导航区域 -->
    <view class="left">
      <view
        v-for="item in leftList"
        :key="item.id"
        class="left_item"
        :class="item.id == selectedId ? 'selected' : ''"
        @click="leftItemClick(item.id)"
      >
        {{ item.title }}
      </view>
    </view>

    <!-- 右侧内容区域 -->
    <view class="right">
      <view v-for="item in rightList" :key="item.id" class="right_item">
        {{ item.content }}
      </view>
    </view>
  </view>
</template>

<script>
export default {
  data() {
    return {
      leftList: [],
      rightList: [],
      selectedId: 1, //左边当前选中id
      itemTopArr: [], //右侧所有item的top数组
    };
  },
  onLoad() {
    this.initData();
    this.getItemTopArr();
  },
  //页面滚动监听
  onPageScroll(e) {
    let scrollTop = e.scrollTop;
    console.log("scrollTop = " + scrollTop);
    for (let i = 0; i < this.itemTopArr.length; i++) {
      if (scrollTop >= this.itemTopArr[i]) {
        this.selectedId = this.rightList[i].parentId;
        console.log("selectedId = " + this.selectedId);
      }
    }
  },
  methods: {
    //左侧item点击
    leftItemClick(id) {
      this.selectedId = id;

      let index = 0;
      for (let i = 0; i < this.rightList.length; i++) {
        if (this.rightList[i].parentId == id) {
          index = i;
          break;
        }
      }

      //将页面滚动到目标位置
      uni.pageScrollTo({
        scrollTop: this.itemTopArr[index],
        duration: 300, //滚动动画时长
      });
    },
    //获取右侧所有item的top数组
    getItemTopArr() {
      this.$nextTick(() => {
        const query = uni.createSelectorQuery().in(this);
        const nodesRef = query.selectAll(".right > .right_item");
        nodesRef
          .fields(
            {
              size: true,
              rect: true,
              scrollOffset: true,
            },
            (res) => {
              res.forEach((item) => {
                this.itemTopArr.push(item.top);
              });
              console.log(this.itemTopArr);
            }
          )
          .exec();
      });
    },
    //初始化数据源
    initData() {
      for (let index = 1; index < 10; index++) {
        for (let i = 1; i < 4; i++) {
          this.rightList.push({
            id: index + "-" + i,
            parentId: index,
            content: "content-" + index,
          });
        }
        this.leftList.push({
          id: index,
          title: "title-" + index,
        });
      }
    },
  },
};
</script>

<style lang="scss" scoped>
.container {
  position: relative;
  min-height: 100vh;
  background: #fff;

  .left {
    position: fixed;
    width: 120px;
    height: 100%;
    min-height: 100vh;
    overflow: auto;
    float: left;
    background: #f2f2f2;

    .left_item {
      width: 100%;
      height: 60px;
      text-align: center;
      line-height: 60px;
    }

    .selected {
      background: #fff;
      font-weight: bold;
      color: #07c160;
    }
  }

  .right {
    margin-left: 120px;
    width: calc(100vw - 120px);
    overflow: auto;

    .right_item {
      width: 100%;
      height: 200px;
      text-align: center;
      line-height: 200px;
      font-size: 24px;
      border-bottom: 1px solid #ccc;
      box-sizing: border-box; //padding、border不影响元素的宽高
    }
  }
}
</style>


在这里插入图片描述

官方onPageScroll方法的使用注意事项(见上图)里说不要在此方法里写复杂的交互,故将onPageScroll里的for循环改写到滚动结束执行:

<template>
  <view class="container">
    <!-- 左侧fixed导航区域 -->
    <view class="left">
      <view
        v-for="item in leftList"
        :key="item.id"
        class="left_item"
        :class="item.id == selectedId ? 'selected' : ''"
        @click="leftItemClick(item.id)"
      >
        {{ item.title }}
      </view>
    </view>

    <!-- 右侧内容区域 -->
    <view class="right">
      <view v-for="item in rightList" :key="item.id" class="right_item">
        {{ item.content }}
      </view>
    </view>
  </view>
</template>

<script>
export default {
  data() {
    return {
      leftList: [],
      rightList: [],
      selectedId: 1, //左边当前选中id
      itemTopArr: [], //右侧所有item的top数组
      timeoutID: null,
    };
  },
  onLoad() {
    this.initData();
    this.getItemTopArr();
  },
  //页面滚动监听
  onPageScroll(e) {
    let scrollTop = e.scrollTop;
    console.log("scrollTop = " + scrollTop);

    clearTimeout(this.timeoutID);
    this.timeoutID = setTimeout(() => {
      console.log("结束滚动");

      for (let i = 0; i < this.itemTopArr.length; i++) {
        if (scrollTop >= this.itemTopArr[i]) {
          this.selectedId = this.rightList[i].parentId;
          console.log("selectedId = " + this.selectedId);
        }
      }
    }, 100);
  },
  methods: {
    //左侧item点击
    leftItemClick(id) {
      this.selectedId = id;

      let index = 0;
      for (let i = 0; i < this.rightList.length; i++) {
        if (this.rightList[i].parentId == id) {
          index = i;
          break;
        }
      }

      //将页面滚动到目标位置
      uni.pageScrollTo({
        scrollTop: this.itemTopArr[index],
        duration: 300, //滚动动画时长
        success: (res) => {
          console.log(res);
          console.log("scroll success");
        },
        fail: (err) => {
          console.log(err);
          console.log("scroll fail");
        },
      });
    },
    //获取右侧所有item的top数组
    getItemTopArr() {
      this.$nextTick(() => {
        const query = uni.createSelectorQuery().in(this);
        const nodesRef = query.selectAll(".right > .right_item");
        nodesRef
          .fields(
            {
              size: true,
              rect: true,
              scrollOffset: true,
            },
            (res) => {
              res.forEach((item) => {
                this.itemTopArr.push(item.top);
              });
              console.log(this.itemTopArr);
            }
          )
          .exec();
      });
    },
    //初始化数据源
    initData() {
      for (let index = 1; index < 10; index++) {
        for (let i = 1; i < 4; i++) {
          this.rightList.push({
            id: index + "-" + i,
            parentId: index,
            content: "content-" + index,
          });
        }
        this.leftList.push({
          id: index,
          title: "title-" + index,
        });
      }
    },
  },
};
</script>

<style lang="scss" scoped>
.container {
  position: relative;
  min-height: 100vh;
  background: #fff;

  .left {
    position: fixed;
    width: 120px;
    height: 100%;
    min-height: 100vh;
    overflow: auto;
    float: left;
    background: #f2f2f2;

    .left_item {
      width: 100%;
      height: 60px;
      text-align: center;
      line-height: 60px;
    }

    .selected {
      background: #fff;
      font-weight: bold;
      color: #07c160;
    }
  }

  .right {
    margin-left: 120px;
    width: calc(100vw - 120px);
    overflow: auto;

    .right_item {
      width: 100%;
      height: 200px;
      text-align: center;
      line-height: 200px;
      font-size: 24px;
      border-bottom: 1px solid #ccc;
      box-sizing: border-box; //padding、border不影响元素的宽高
    }
  }
}
</style>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/401886.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

JVM结构-类加载(类加载子系统,类加载的角色,类加载的过程,类加载器分类,双亲委派机制,类的主/被动使用)

JVM 结构-类加载2.1类加载子系统2.2类加载的角色2.3类加载的过程2.3.1加载2.3.2链接2.3.3初始化2.4类加载器分类2.4.1 引导类加载器2.4.2扩展类加载器2.4.3应用程序类加载器2.5双亲委派机制2.6类的主动/被动使用2.1类加载子系统 类加载器子系统负责从文件系统或者网络中加载 cl…

【深度强化学习】(1) DQN 模型解析,附Pytorch完整代码

大家好&#xff0c;今天和各位讲解一下深度强化学习中的基础模型 DQN&#xff0c;配合 OpenAI 的 gym 环境&#xff0c;训练模型完成一个小游戏&#xff0c;完整代码可以从我的 GitHub 中获得&#xff1a; https://github.com/LiSir-HIT/Reinforcement-Learning/tree/main/Mod…

腾讯云新用户怎么配置服务器的方法教程

腾讯云新用户怎么配置服务器&#xff1f;腾讯云服务器配置选择攻略&#xff0c;先选择云服务器地域和可用区&#xff0c;然后根据用户使用场景需要平衡型、计算型或高IO型等特性来选择云服务器CVM实例规格&#xff0c;主机教程网来详细说下腾讯云服务器配置选择攻略。 1、腾讯云…

政府工作报告连提9年科技创新 企业研发如何“又快又好”

今年的政府工作报告&#xff0c; “科技创新” 这一描述连续出现7次&#xff0c;这也是自2015年开始&#xff0c; “科技创新” 这一概念在全国“两会”政府工作报告中连续九年被提到。政府工作报告指出&#xff0c;科技政策要聚焦自立自强&#xff0c;完善新型举国体制&#x…

ccc-pytorch-LSTM(8)

文章目录一、LSTM简介二、LSTM中的核心结构三、如何解决RNN中的梯度消失/爆炸问题四、情感分类实战&#xff08;google colab&#xff09;一、LSTM简介 LSTM&#xff08;long short-term memory&#xff09;长短期记忆网络&#xff0c;RNN的改进&#xff0c;克服了RNN中“记忆…

ArcGIS动态表格批量出图

一.产品介绍&#xff1a;ArcGIS动态表格扩展模块Mapping and Charting Solutions&#xff0c;可用于插入动态表格&#xff0c;与数据驱动结合&#xff0c;出图效率无敌。注&#xff1a;优先选择arcgis10.2.2。 二、下载连接&#xff1a; https://www.xsoftnet.com/share/a001CX…

Idea+maven+spring-cloud项目搭建系列--12 整合grpc

前言&#xff1a; grpc 是geogle 开源的rpc 通信框架&#xff0c;通过定义proto生成通信存根&#xff0c;像本地调用服务一样&#xff0c;进行远程服务的调用&#xff1b; 1 消费端服务提供&#xff1a; 1.1 引入grpc 和 protobuf <!-- RPC --> <!-- RPC 服务调用 …

最大子矩阵(蓝桥杯)暴搜 JAVA

题目描述&#xff1a; 小明有一个大小为NM的矩阵&#xff0c;可以理解为一个N行M列的二维数组。 我们定义一个矩阵m 的稳定度f(m) 为f(m)max(m)-min(m)。 其中max(m)表示矩阵m中的最大值&#xff0c;min(m) 表示矩阵m 中的最小值。 现在小明想要从这个矩阵中找到一个稳定度不大…

2023-03-09干活小计

强化学习&#xff1a; 强化学习用智能体&#xff08;agent&#xff09;这个概念来表示做决策的机器。 感知、决策和奖励 感知。智能体在…

【ECCV 2022】76小时动捕,最大规模数字人多模态数据集开源

随着元宇宙的火爆以及数字人建模技术的商业化&#xff0c;AI 数字人驱动算法&#xff0c;作为数字人动画技术链的下一关键环节&#xff0c;获得了学界和工业界越来越广泛的兴趣和关注。其中谈话动作生成 &#xff08;由声音等控制信号生成肢体和手部动作&#xff09;由于可以降…

ChatGPT正当时,让我们一起深耕智能内容生成和智能内容增强领域

ChatGPT以其强大的信息整合和对话能力惊艳了全球&#xff0c;在自然语言处理上面表现出了惊人的能力。很多人都预测 2023 年将是 AI 生成之年&#xff0c;也许我们将迎来继农业革命、工业革命以来的第三种通用技术的普及。 信必优长期专注于人工智能领域&#xff0c;拥有产品研…

力扣-求关注者的数量

大家好&#xff0c;我是空空star&#xff0c;本篇带大家了解一道简单的力扣sql练习题。 文章目录前言一、题目&#xff1a;1729. 求关注者的数量二、解题1.正确示范①提交SQL运行结果2.正确示范②提交SQL运行结果3.正确示范③提交SQL运行结果4.正确示范④提交SQL运行结果5.正确…

Linux下创建ln链接文件

1.linux重定向命令 >ls > a.txt将ls显示的结果 输出到文件中1.echo "hello world"2.往终端上输出 字符串"hello world"echo "hello " >c.txt 将"hello "字符串 输出到文件中&#xff08;覆盖&#xff09;echo "world&qu…

MFC 简单使用事件

功能三个按钮,一个静态框,默认值是0,增加减少按钮和退出按钮.增加减少按钮显示在静态框中.退出按钮退出软件.实验事件思路新建三个事件,add事件sub事件quit事件,一个按钮触发一个事件,静态框新建一个线程接受事件做出对应的改变.UI添加的代码就不具体说,具体说下事件的代码,这才…

SpringBoot项目使用Schedule注释创建定时任务

文章目录知识讲解相关注释&#xff08;主要两个,EnableScheduling和Scheduled&#xff09;scheduled的cron语法代码项目目录结构启动类&#xff08;Application&#xff09;定时任务类(Task)配置类&#xff08;application.properties&#xff09;pom依赖展望&#xff08;Quart…

环形链表相关的练习

目录 一、相交链表 二、环形链表 三、环形链表 || 一、相交链表 给你两个单链表的头节点 headA 和 headB &#xff0c;请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点&#xff0c;返回 null 。 图示两个链表在节点 c1 开始相交&#xff1a; 题目数据…

基于Three.js和MindAR实现的网页端WebAR人脸识别追踪功能的京剧换脸Demo(含源码)

前言 近段时间一直在玩MindAR的功能&#xff0c;之前一直在弄图片识别追踪的功能&#xff0c;发现其强大的功能还有脸部识别和追踪的功能&#xff0c;就基于其面部网格的例子修改了一个国粹京剧的换脸程序。如果你不了解MindAR的环境配置可以先参考这篇文章&#xff1a;基于Mi…

本地存储localStorage、sessionStorage

目录 一、localStorage 二、sessionStorage 三、本地存储处理复杂数据 一、localStorage 介绍 &#xff08;1&#xff09;数据存储在用户浏览器中 &#xff08;2&#xff09;设置、读取方便、甚至页面刷新不会丢失数据 &#xff08;3&#xff09;容量较大&#xff0c;se…

408考研计算机之计算机组成与设计——知识点及其做题经验篇目3:指令的寻址方式

上篇文章我们讲到&#xff0c;指令的基本格式&#xff0c;一条指令通常包括操作码字段和地址码字段两部分&#xff1a; 操作码字段地址码字段并且我们还讲到根据操作数地址码的数目不同&#xff0c;可将指令分为零一二三四地址指令。感兴趣的小伙伴们可以看看小编的上一篇文章…

贝塞尔曲线介绍及其应用

贝塞尔样条是一个允许用户控制节点处斜率的样条&#xff0c;是一种特殊的三次样条。   皮埃尔贝塞尔在其为雷诺&#xff08;Renault&#xff09;汽车公司工作时有了这个创意。Paul de Casteljau在与雷诺竞争关系的汽车公司雪铁龙Citroen公司工作时也独立有了这个想法。这在两…