【vue scrollTo 数据无限滚动 】

news2024/11/24 23:41:31

vue数据无限滚动
参考来源 Vue3 实现消息无限滚动的新思路 —— 林三心不学挖掘机
在这里插入图片描述
vue3代码

<template>
  <div class="scroll-container" ref="scrollRef">
    <div v-for="(item, index) in list" :key="index" style="height: 40px; line-height: 40px;">{{ item.title }}</div>
  </div>
</template>

<script setup>
import  { onMounted, ref } from 'vue'
defineOptions({name: 'publicRecruitment-bountyDisplay'})

// 容器的 dom 节点
const scrollRef = ref()
// 模拟列表数据
const dataSource = new Array(10).fill(0).map((_, index) => ({
  title: `这是一条信息${index}`
}))
const list = ref([...dataSource])

// 记录原始数据的长度
const len = dataSource.length
onMounted(() => {
  // 滚动的距离
  let top = 0
  // 索引
  let index = 0

  const scroll = () => {
    // 垂直方向滚动
    scrollRef.value?.scrollTo({
      top: top++
    })
    if (top % 40 === 0) {
      // 哪一项滚不见了,就拿这一项 push 到列表中
      const target = list.value[index]

      if (target) list.value.push(target)
      
      if (index < (len - 1)) {
        // 不断递增
        index++
      } else {
        // 刚好滚动完一轮,重新来过,初始化数据
        top = 0
        index = 0
        scrollRef.value?.scrollTo({
          top: 0
        })
        list.value = [...dataSource]
      }
    }
    // 不断滚动
    requestAnimationFrame(scroll)
  }

  scroll()
})
</script>

<style lang="scss" scoped>
.scroll-container {
  //   防止有滚动条出现
  overflow: hidden;
  height: 150px;
}
</style>

兼容升级版本
1.如果数据长度形成的总高度少于容器高度,不设置滚动
2.如果数据长度仅高于容器高度不足一个数据单位的长度会出现抖动滚动。解决方法:将数据复制一份

删减代码

在这里插入图片描述

<!-- 滚动展示 -->
<template>
  <div style="height: 100%; width: 100%;">
    <div class="mb-3" style="font-size: 13px; color: #666;">无缝衔接滚动</div>
    <!-- 滚动 -->
    <div
      class="scroll-container"
      ref="scrollRef"
      style="height: calc(100% - 32px); overflow: hidden; font-size: 13px;color: #333;"
    >
      <!-- 数据list -->
      <div
        v-for="(item) in list"
        :key="item.name"
        class="d-flex justify-space-between align-center"
        :style="`height: ${dataItemHeight}px;`"
      >
        <div class="ml-2">{{ item.name }}</div>
      </div>
    </div>
  </div>
</template>

<script setup>
import  { onMounted, ref } from 'vue'
defineOptions({name: 'publicRecruitment-bountyDisplay'})
// 滚动实现代码部分
const dataItemHeight = 40
// 容器的 dom 节点
const scrollRef = ref()
// // 模拟列表数据
let listSource = new Array(10).fill(0).map((_, index) => ({ name: `name${index}`}))
const list = ref([...listSource])

// 记录原始数据的长度
let len = listSource.length
onMounted(() => {
  // 滚动的距离
  let top = 0
  // 索引
  let index = 0
  const scroll = () => {
    // 垂直方向滚动
    scrollRef.value?.scrollTo({
      top: top++,
    })
    if (top % dataItemHeight === 0) {
      // 哪一项滚不见了,就拿这一项 push 到列表中
      const target = list.value[index]
      if (target) list.value.push(target)

      if (index < len - 1) {
        // 不断递增
        index++
      } else {
        // 刚好滚动完一轮,重新来过,初始化数据
        top = 0
        index = 0
        scrollRef.value?.scrollTo({
          top: 0,
        })
        list.value = [...listSource]
      }
    }
    // 不断滚动
    requestAnimationFrame(scroll)
  }
  // 如果数据长度形成的总高度少于容器高度,不设置滚动
  const clientHeight = scrollRef.value?.clientHeight
  if (len*dataItemHeight > clientHeight) {
    if ((len - 1)*dataItemHeight < clientHeight) {
      // 如果clientHeight刚好大于len*dataItemHeight,但不满足(len+1)*dataItemHeight会出现抖动。
      // 解决方法:将数据复制一份
      listSource = listSource.concat(...Array.from({ length: 1 }, () => [...listSource]))
      list.value = listSource
      len = listSource.length
    }
    scroll()
  }
})
</script>
<style lang="scss" scoped>
.red {
  color: red;
}
.ellipsisText {
  // width: 120px;
  white-space: nowrap;
  text-overflow: ellipsis;
  overflow: hidden;
}
</style>

完整代码

在这里插入图片描述

<!-- 滚动展示 -->
<template>
  <div style="height: 100%; width: 100%;">
    <div class="mb-3" style="font-size: 13px; color: #666;">最近30天已有<span class="red">68</span>提现成功,累计提现<span class="red">9450</span></div>
    <!-- 滚动 -->
    <div
      class="scroll-container"
      ref="scrollRef"
      style="height: calc(100% - 32px); overflow: hidden; font-size: 13px;color: #333;"
    >
      <!-- 数据list -->
      <div
        v-for="(item) in list"
        :key="item[keyText] || item.name"
        class="d-flex justify-space-between align-center"
        :style="`height: ${dataItemHeight}px;`"
      >
        <!-- 头像、用户名 -->
        <div class="d-flex align-center">
          <v-avatar size="30" :image="item.avatar || 'https://minio.citupro.com/dev/menduner/7.png'"></v-avatar>
          <div class="ml-2">{{ formatName(item.name) }}</div>
          <!-- <div class="ml-2">{{ item.name }}</div> -->
        </div>
        <div class="d-flex" style="width: calc(100% - 65px);">
          <!-- 内容 -->
          <div class="d-flex ellipsisText mx-4" style="flex: 1;">
            <div>推荐到</div>
            <div class="ellipsisText ml-1" style="max-width: 100px;">{{ item.company }}</div>
            <div class="ellipsisText ml-1" style="max-width: 60px;">{{ item.job }}</div>
          </div>
          <!-- 赏金 -->
          <div>提现¥<span class="red">{{ item.money }}</span></div>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup>
import  { onMounted, ref } from 'vue'

defineOptions({name: 'publicRecruitment-bountyDisplay'})
defineProps({
  keyText: {
    type: String,
    default: 'id'
  }
})
const avatarList = [
  'https://img0.baidu.com/it/u=230622178,1565949306&fm=253&fmt=auto&app=138&f=JPEG?w=449&h=300',
  'https://img0.baidu.com/it/u=1401084042,2724457850&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=726',
  'https://img1.baidu.com/it/u=3995643348,1848098846&fm=253&fmt=auto&app=138&f=JPEG?w=800&h=800',
  'https://img0.baidu.com/it/u=230622178,1565949306&fm=253&fmt=auto&app=138&f=JPEG?w=449&h=300',
  'https://img0.baidu.com/it/u=1401084042,2724457850&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=726',
  'https://img1.baidu.com/it/u=3995643348,1848098846&fm=253&fmt=auto&app=138&f=JPEG?w=800&h=800',
  'https://img0.baidu.com/it/u=230622178,1565949306&fm=253&fmt=auto&app=138&f=JPEG?w=449&h=300',
]
let listSource = []
for (let index = 0; index < 68; index++) {
  const obj = {
    id: 'id' + (index+1),
    name: '用户' + (index+1),
    // name: (index+1),
    avatar: avatarList[index % 7],
    company: '某某公司' + (index+1),
    job: '某某职位' + (index+1),
    money: index*index*(100 - index) || 100,
  }
  listSource.push(obj)
}

// 用户名加*号
const formatName = (name) => {
  if (!name.length) {
    return name
  } else if (name.length === 1) {  
    return name // 如果名字只有一个字,则直接返回该字  
  } else if (name.length === 2) {  
    return name.charAt(0) + '*' // 如果名字有两个字,则返回第一个字后跟一个星号  
  } else {  
    return name.charAt(0) + '**' // 如果名字有多于两个字,则返回第一个字后跟两个星号  
  }  
}

// 滚动实现代码部分
const dataItemHeight = 40
// 容器的 dom 节点
const scrollRef = ref()
// // 模拟列表数据
// const listSource = new Array(10).fill(0).map((_, index) => ({ title: `这是一条信息${index}`}))
const list = ref([...listSource])

// 记录原始数据的长度
let len = listSource.length
onMounted(() => {
  // 滚动的距离
  let top = 0
  // 索引
  let index = 0
  const scroll = () => {
    // 垂直方向滚动
    scrollRef.value?.scrollTo({
      top: top++,
    })
    if (top % dataItemHeight === 0) {
      // 哪一项滚不见了,就拿这一项 push 到列表中
      const target = list.value[index]
      if (target) list.value.push(target)

      if (index < len - 1) {
        // 不断递增
        index++
      } else {
        // 刚好滚动完一轮,重新来过,初始化数据
        top = 0
        index = 0
        scrollRef.value?.scrollTo({
          top: 0,
        })
        list.value = [...listSource]
      }
    }
    // 不断滚动
    requestAnimationFrame(scroll)
  }
  // 如果数据长度形成的总高度少于容器高度,不设置滚动
  const clientHeight = scrollRef.value?.clientHeight
  if (len*dataItemHeight > clientHeight) {
    if ((len - 1)*dataItemHeight < clientHeight) {
      // 如果clientHeight刚好大于len*dataItemHeight,但不满足(len+1)*dataItemHeight会出现抖动。
      // 解决方法:将数据复制一份
      listSource = listSource.concat(...Array.from({ length: 1 }, () => [...listSource]))
      list.value = listSource
      len = listSource.length
    }
    scroll()
  }
})
</script>
<style lang="scss" scoped>
.red {
  color: red;
}
.ellipsisText {
  // width: 120px;
  white-space: nowrap;
  text-overflow: ellipsis;
  overflow: hidden;
}
</style>

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

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

相关文章

基于Sringboot+Vue的校园招聘系统【原创】【开源】

浏览器&#xff1a;Chrome或360浏览器 系统环境配置 前置条件&#xff1a;系统已经安装了Mysql5.7、Mysql工具&#xff08;Navicat&#xff09;、JDK1.8、Maven3.6.1、vue3.0以下开发环境、 Intellij Idea、 Chrome或360浏览器 1、导入数据库 2、编译前端代码vue 编译&…

帮企商城10合一万能DIY分销商城小程序源码系统 带源代码包+搭建部署教程

系统概述 这是一款集多种功能于一体的源码系统&#xff0c;旨在为用户提供一站式的商城解决方案。它不仅支持小程序端&#xff0c;还能与其他平台无缝对接&#xff0c;满足不同用户的需求。 代码示例 系统特色功能一览 1.万能 DIY 功能&#xff1a;用户可以根据自己的需求和创…

视频云沉浸式音视频技术能力探索与建设

概述 随着传输技术、显示技术与算力的持续提升&#xff0c;用户对于音视频体验的需求在提高&#xff0c;各家设备厂商也在探索和推出对应的技术与产品。打造空间感的空间视频与空间音频是其中最为关键的2项技术&#xff0c;bilibili视频云在这两项技术领域也进行了相关代探索与…

足底筋膜炎的症状

足底筋膜炎是足底的肌腱或者筋膜发生无菌性炎症所致&#xff0c;其症状主要包括&#xff1a; 1、疼痛&#xff1a;这是足底筋膜炎最常见和突出的症状。疼痛通常出现在足跟或足底近足跟处&#xff0c;有时压痛较剧烈且持续存在。晨起时或长时间不活动后&#xff0c;疼痛感觉尤为…

计算机系统基础(一)

1. 引入——从源程序到可执行文件 了解高级语言编写的代码在后台是如何被编译并运行的 首先我们会编写一段代码&#xff0c;例如 #include<stdio.h>int main(){printf("hello world!\n");return 0; } 并把它命名为hello.c文件 预处理阶段 接下来通过命令…

数据结构--单链表(图文)

单链表的概念 在单链表中&#xff0c;每个元素&#xff08;称为节点&#xff09;包含两部分&#xff1a;一部分是存储数据的数据域&#xff0c;另一部分是存储下一个节点地址的指针域。这里的“单”指的是每个节点只有一个指向下一个节点的指针。 节点&#xff1a;链表中的基…

网络协议安全:TCP/IP协议栈的安全问题和解决方案

「作者简介」:北京冬奥会网络安全中国代表队,CSDN Top100,就职奇安信多年,以实战工作为基础对安全知识体系进行总结与归纳,著作适用于快速入门的 《网络安全自学教程》,内容涵盖Web安全、系统安全等12个知识域的一百多个知识点,持续更新。 这一章节我们需要知道TCP/IP每…

2024最新最全【网络安全/渗透测试】面试题汇总

思路流程 信息收集漏洞挖掘漏洞利用&权限提升清除测试数据&输出报告复测 问题深信服一面:SQL注入防护为什么参数化查询可以防止sql注入SQL头注入点盲注是什么&#xff1f;怎么盲注&#xff1f;宽字节注入产生原理以及根本原因 产生原理在哪里编码根本原因解决办法sql里…

Kafka中的时间轮算法

1. Kafka与时间轮&#xff1a; Kafka的定时器底层使用时间轮算法。Kafka时间轮是层次时间轮&#xff0c;并且支持时间轮复用。 优点&#xff1a; 高效的插入操作&#xff1a; 时间轮底层数据结构&#xff08;桶&#xff09;&#xff0c;使用双向链表的设计使得插入操作的时间…

掌握JavaScript ES6精髓:探索函数和对象的高级扩展与实用技巧

序言 JavaScript&#xff0c;作为前端开发中不可或缺的语言&#xff0c;已经发展到了ECMAScript 2015&#xff08;简称ES6&#xff09;以及后续的版本。ES6带来了诸多语法上的改进和创新&#xff0c;使得代码更加简洁、优雅&#xff0c;同时也提供了更多的编程模式和实用技巧。…

Python-面向对象编程(超详细易懂)

面向对象编程&#xff08;oop&#xff09; 面向对象是Python最重要的特性&#xff0c;在Python中一切数据类型都是面向对象的。 面向对象的编程思想&#xff1a;按照真实世界客观事物的自然规律进行分析&#xff0c;客观世界中存在什么样的实体&#xff0c;构建的软件系统就存在…

Docker搭建yolov8并训练自己的数据集(包会)

本文通过docker的方式搭建yolov8运行环境&#xff0c;并成功训练了自己的数据集&#xff08;化学仪器数据集&#xff09;。 1、安装docker 在一台通往的服务器上安装docker&#xff0c;建议参考我之前的文章&#xff1a;Docker基础学习-CSDN博客 2、创建yolov8镜像 首先编写…

openresty(Nginx) 301重定向域名 http访问强制使用https

1 访问http 2 修改配置访问 server {listen 80;server_name example.cn;return 301 https://$server_name$request_uri;access_log /data/logs/czgzzfjgsup_access.log access;error_log /data/logs/czgzzfjg_error.log error;#location / {root /usr/local/open…

【Linux进程】Linux下的---七大进程状态(什么是进程状态?Linux下有哪些进程状态?)

目录 一、前言 二、什么是进程状态&#xff1f; 三、操作系统(OS)下的 --- 进程状态 &#x1f525;运行状态&#x1f525; &#x1f525;阻塞状态&#x1f525; &#x1f525;挂起状态&#x1f525; 四、Linux下的7种进程状态 &#x1f525;运行状态 -- R&#x1f525;…

内存优化技巧:让数据处理更高效

Pandas无疑是我们数据分析时一个不可或缺的工具&#xff0c;它以其强大的数据处理能力、灵活的数据结构以及易于上手的API赢得了广大数据分析师和机器学习工程师的喜爱。 然而&#xff0c;随着数据量的不断增长&#xff0c;如何高效、合理地管理内存&#xff0c;确保Pandas Da…

vue中实现百度地图全国与省市地图切换

前言 本文主要是用于示例全国地图&#xff0c;点击省市地图直接跳转到该省市地图并展示&#xff0c;可以拓展在地图上显示标记点&#xff08;本文未做示例&#xff09;&#xff0c;后续有完整代码&#xff0c;但是由于需要与本来项目业务代码进项分割&#xff0c;可能会有些问题…

centos 7无需token编译安装freeswitch 1.10.11 ——筑梦之路

准备工作 安装编译工具和依赖包 yum update -y sudo yum install epel-release vim tcpdump net-tools.x86_64 -y sudo yum install gcc-c sqlite-devel zlib-devel libcurl-devel pcre-devel speex-devel ldns-devel libedit-devel openssl-devel git -y yum install yasm n…

Web APIs--Dom获取属性操作

目录 1.DOM&#xff08;操作网页内容、用户交互&#xff09; 2.DOM对象获取&#xff08;querySelect(‘’)、querySelectAll(‘’)&#xff09; 总结&#xff1a; 3.操作元素内容&#xff08;修改元素的文本更换内容&#xff09; 1. 元素innerText 属性 2.元素.innerHTML…

JavaSE 面向对象程序设计初级 静态static 包package 常量final 代码块 代码实操理论内存原理详解

目录 static(静态) 静态的特点 应用示例 静态变量 静态方法 注意事项 内存图 重新认识main方法 包 什么是包 使用导包在什么时候 final关键字 常量 命名规范 细节&#xff08;重点&#xff09; 权限修饰符 代码块 局部代码块 构造代码块 静态代码块 个人号…

【机器学习】必会降维算法之:随机投影(Random Projection)

随机投影&#xff08;Random Projection&#xff09; 1、引言2、随机投影&#xff08;Random Projection&#xff09;2.1 定义2.2 核心原理2.3 应用场景2.4 实现方式2.5 算法公式2.6 代码示例 3、总结 1、引言 小屌丝&#xff1a;鱼哥&#xff0c;降维算法还没讲完呢。 小鱼&a…