当前位置:首页 > 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. 清除定时器和动画帧防止内存泄漏

分享给朋友:

相关文章

jquery列表

jquery列表

jQuery 列表操作 jQuery 提供了多种方法来操作 HTML 列表(如 <ul> 或 <ol>),包括动态添加、删除、修改列表项,以及事件绑定等。 创建列表 使用 j…

vue实现列表分类

vue实现列表分类

Vue 实现列表分类的方法 使用计算属性分类 通过计算属性对原始数组进行分类处理,返回分组后的对象或数组。适用于静态数据或需要响应式更新的场景。 computed: { categorizedI…

vue实现列表展示

vue实现列表展示

Vue 实现列表展示 在 Vue 中实现列表展示通常使用 v-for 指令,结合数据绑定和动态渲染功能。以下是几种常见的实现方式: 基础列表渲染 使用 v-for 指令遍历数组,动态生成列表项。假…

vue实现分类列表

vue实现分类列表

Vue 实现分类列表的方法 数据结构设计 使用数组存储分类数据,每个分类对象包含 id、name 等属性,子分类通过 children 字段嵌套。例如: categories: [ {…

vue实现视频列表

vue实现视频列表

Vue 实现视频列表 在 Vue 中实现视频列表通常需要结合数据绑定、组件化和第三方库(如视频播放器)。以下是具体实现方法: 数据准备 创建一个数组存储视频信息,包括标题、封面图、视频链接等: d…

vue实现列表高亮

vue实现列表高亮

Vue 列表高亮实现方法 动态类绑定 通过 v-bind:class 或简写 :class 实现条件高亮 <template> <ul> <li…