当前位置:首页 > React

react实现滚动新闻列表

2026-01-27 13:18:32React

实现滚动新闻列表的基本思路

使用React实现滚动新闻列表可以通过CSS动画或JavaScript定时控制两种方式完成。核心逻辑是通过动态更新数据或样式,模拟新闻条目的向上滚动效果。

CSS动画实现方案

利用CSS的@keyframestransform属性实现平滑滚动效果,React负责数据渲染:

react实现滚动新闻列表

import React, { useState } from 'react';
import './NewsTicker.css';

function NewsTicker({ items }) {
  return (
    <div className="ticker-container">
      <div className="ticker-content">
        {items.map((item, index) => (
          <div key={index} className="ticker-item">{item}</div>
        ))}
        {/* 复制一份实现无缝循环 */}
        {items.map((item, index) => (
          <div key={`copy-${index}`} className="ticker-item">{item}</div>
        ))}
      </div>
    </div>
  );
}

配套CSS文件(关键部分):

.ticker-container {
  height: 60px;
  overflow: hidden;
  position: relative;
}

.ticker-content {
  position: absolute;
  animation: scroll 20s linear infinite;
}

@keyframes scroll {
  0% { transform: translateY(0); }
  100% { transform: translateY(-50%); }
}

.ticker-item {
  height: 60px;
  display: flex;
  align-items: center;
}

JavaScript定时控制方案

通过setInterval动态更新数据实现更灵活的控制:

react实现滚动新闻列表

import React, { useState, useEffect } from 'react';

function NewsTicker({ items }) {
  const [displayItems, setDisplayItems] = useState(items);

  useEffect(() => {
    const interval = setInterval(() => {
      setDisplayItems(prev => {
        const newItems = [...prev];
        const firstItem = newItems.shift();
        return [...newItems, firstItem];
      });
    }, 2000);

    return () => clearInterval(interval);
  }, []);

  return (
    <div style={{ height: '60px', overflow: 'hidden' }}>
      {displayItems.map((item, index) => (
        <div key={index} style={{ height: '60px' }}>{item}</div>
      ))}
    </div>
  );
}

性能优化建议

对于大量新闻数据,建议使用虚拟滚动技术。以下是简化实现示例:

import React, { useState, useEffect, useRef } from 'react';

function VirtualScrollTicker({ items }) {
  const [startIndex, setStartIndex] = useState(0);
  const containerRef = useRef(null);
  const visibleCount = 5;

  useEffect(() => {
    const interval = setInterval(() => {
      setStartIndex(prev => (prev + 1) % items.length);
    }, 1000);
    return () => clearInterval(interval);
  }, [items.length]);

  const visibleItems = [];
  for (let i = 0; i < visibleCount; i++) {
    const index = (startIndex + i) % items.length;
    visibleItems.push(items[index]);
  }

  return (
    <div ref={containerRef} style={{ height: `${visibleCount * 60}px`, overflow: 'hidden' }}>
      {visibleItems.map((item, i) => (
        <div key={i} style={{ height: '60px' }}>{item}</div>
      ))}
    </div>
  );
}

完整组件示例

结合动画和暂停功能的增强版实现:

import React, { useState, useEffect, useRef } from 'react';

function AdvancedNewsTicker({ items, speed = 50 }) {
  const [isPaused, setIsPaused] = useState(false);
  const containerRef = useRef(null);
  const contentRef = useRef(null);
  const animationRef = useRef(null);
  const positionRef = useRef(0);

  useEffect(() => {
    const animate = () => {
      if (!isPaused) {
        positionRef.current -= 1;
        contentRef.current.style.transform = `translateY(${positionRef.current}px)`;

        if (-positionRef.current >= contentRef.current.clientHeight / 2) {
          positionRef.current = 0;
        }
      }
      animationRef.current = requestAnimationFrame(animate);
    };

    animationRef.current = requestAnimationFrame(animate);
    return () => cancelAnimationFrame(animationRef.current);
  }, [isPaused]);

  return (
    <div 
      ref={containerRef}
      style={{ 
        height: '60px',
        overflow: 'hidden',
        position: 'relative'
      }}
      onMouseEnter={() => setIsPaused(true)}
      onMouseLeave={() => setIsPaused(false)}
    >
      <div 
        ref={contentRef}
        style={{
          position: 'absolute',
          width: '100%'
        }}
      >
        {items.map((item, i) => (
          <div key={i} style={{ height: '60px' }}>{item}</div>
        ))}
        {items.map((item, i) => (
          <div key={`clone-${i}`} style={{ height: '60px' }}>{item}</div>
        ))}
      </div>
    </div>
  );
}

注意事项

  1. 确保为滚动容器设置固定高度和overflow: hidden
  2. 实现无缝循环需要复制一份数据或使用模运算
  3. 移动端注意触摸事件处理
  4. 大量数据时推荐使用虚拟滚动技术
  5. 清除定时器和动画帧防止内存泄漏

分享给朋友:

相关文章

vue实现列表水印

vue实现列表水印

实现列表水印的方法 在Vue中为列表添加水印可以通过多种方式实现,以下是几种常见的方法: 使用CSS背景图 通过CSS的background-image属性为列表元素添加水印背景。水印可以是文字或…

vue公共列表的实现

vue公共列表的实现

Vue 公共列表的实现方法 在 Vue 中实现公共列表组件,可以通过封装可复用的逻辑和模板来完成。以下是几种常见的实现方式: 使用 props 和 slots 通过 props 接收列表数据,使用…

h5 实现列表

h5 实现列表

列表实现方法 在HTML5中,可以通过多种方式实现列表,包括无序列表、有序列表和自定义列表。以下是具体的实现方法。 无序列表 无序列表使用<ul>标签,列表项使用<li>标…

jquery 列表

jquery 列表

jQuery 列表操作 jQuery 提供了多种方法来操作 HTML 列表(如 <ul> 或 <ol>)。以下是一些常见的操作方式: 动态添加列表项 使用 append()…

vue实现搜索列表

vue实现搜索列表

Vue 实现搜索列表功能 在 Vue 中实现搜索列表功能通常需要以下几个关键步骤: 数据绑定与列表渲染 使用 v-model 绑定搜索输入框,监听用户输入。通过 v-for 指令渲染过滤后的列表数据…

uniapp 内容列表

uniapp 内容列表

uniapp 内容列表的实现方法 在uniapp中实现内容列表通常需要结合组件和数据绑定。以下是一个常见的方法: 模板部分 <template> <view class=…