发布于 2026-01-06 1 阅读
0

如何使用 React 构建图片轮播图

如何使用 React 构建图片轮播图

标题图片

大家好!

在这篇文章中,我决定使用我目前非常热衷的技术——React。

最近,我有很多机会接触 React,随着它的优势越来越清晰,我越来越愿意深入学习使用这个库来构建用户界面。

如您所知,React是一个 JavaScript 库,它采用组件化的方式构建复杂的交互式用户界面。React 使用的一些技术和概念旨在提高界面交互的效率。通过使用虚拟 DOM(真实 DOM 的轻量级表示),React 可以显著提升界面交互的速度。因为每次更改发生时,React 都会将虚拟 DOM 与真实 DOM 进行比较,并仅更新已更改的部分。

好了,这只是 React 在构建 UI 时比其他库强大得多的原因之一。本文将重点介绍 React 的实际应用示例,如果您在阅读代码时遇到困难,或者对文中提到的任何概念不了解,可以查阅 React文档。

基于组件的思维

创建用户界面时,首先要考虑的就是将其视为一组组件,这些组件将封装界面的各个部分,然后协同工作以创造良好的用户体验。这就是 React 的作用之一,它改变了你组织应用程序的方式。

如果你看看这篇文章的标题图片,就能明白我们要构建的是什么了。看起来很简单,对吧?事实上,因为我们用的是 React,所以它确实可以很简单 :)

你应该知道,在 React 中实现图片轮播图的方法有很多,包括组件的组织方式,甚至组件的数量。在这个例子中,我决定创建三个基本组件:第一个组件(`<image>` Carousel)将作为整个布局和逻辑的包装器;第二个ImageSlide组件(`<image>`)将简单地渲染轮播图的图片;第三个Arrow组件(`<array>`)将作为轮播图过渡的左右箭头。这样,对于ImageSlide你作为轮播图输入的每张图片,你都会有一个 `<image>` 组件的实例;而Arrow对于每个箭头,你都会有两个 `<array>` 组件的实例。

首先,让我们来构建Carousel组件。

Carousel组件

首先,你必须告诉 React 你想让它在 HTML 文件的哪个部分渲染你的组件。

在您的 HTML 文件中添加以下内容:

<div id="container">
  <!-- Your component will be rendered here. -->
</div>
Enter fullscreen mode Exit fullscreen mode

在你的 JavaScript 文件中,输入以下内容:

ReactDOM.render(
  <Carousel />,
  document.getElementById('container')
);
Enter fullscreen mode Exit fullscreen mode

如您所见,我们将 div 容器绑定到 Carousel 组件,因此 React 将使用该占位符来渲染您的整个组件。

请注意,您的脚本中必须包含所需的React库。如果您在CodePenJsFiddleReactDOM等代码测试平台进行测试,只需在设置部分添加相关脚本即可。但是,如果您已经在本地计算机上配置了 React 开发环境,那么您应该知道该怎么做了 :)

现在是时候设置我们的Carousel组件了。

class Carousel extends React.Component {
  render () {
    return (
      <div className="carousel"></div>
    );
  }
}
Enter fullscreen mode Exit fullscreen mode

这里我们创建一个简单的包装类,它将负责处理界面中的所有逻辑。该类的 render 方法将返回整个布局的标记,因此我们将所有其他组件添加到div返回的块中。

你应该注意到,这里我们扩展了React.Component类,以声明这个特定的类将是一个 React 组件。需要指出的是,这是 ES6 中对应React.createClass方法的等效实现。前者只是 ES6 特性集中提供的“语法糖”。因此,在实现组件方法时,你会遇到一些差异。可以参考 Todd Motto 的这篇精彩文章,了解每种选项的详细信息。

既然我们已经完成了类的设置Carousel,就应该开始考虑要在类内部渲染什么内容了。

ImageSlide组件

这将是一个非常简单的组件,没有任何逻辑。这是 React 组件构建中常见的模式,这类组件被称为“无状态组件”(stateless或“无functional状态组件”)。原因在于,这类组件没有声明状态,因此缺乏控制状态的逻辑。它们最终只是简单的 JavaScript 函数,接收(或不接收)参数,并返回基于这些输入值构建的(或不返回)标记。

我们来看看这个ImageSlide组件长什么样。

const ImageSlide = ({ url }) => {
  const styles = {
    backgroundImage: `url(${url})`,
    backgroundSize: 'cover',
    backgroundPosition: 'center'
  };

  return (
    <div className="image-slide" style={styles}></div>
  );
}
Enter fullscreen mode Exit fullscreen mode

您可以看到,这个组件的功能并不多。它基本上只需要接收图片 URL,并生成所需的标记,使其作为轮播图中的一张幻灯片即可。

ImageSlide这是一个接收字符串(即图片 URL)的函数,它会创建一个对象来描述组件的样式,并返回填充了我们提供的信息的标记。如前所述,对于您在图片数组中提供的每个 URL,都会有一个这样的组件实例。

关于这个组件的样式,您可以看到图片被设置为背景。不过,您可以根据自己的喜好设置组件的样式,这不会影响本文的目的。

因此,在创建完图像幻灯片的标记后,我们应该将其添加到Carousel组件的渲染方法中。

class Carousel extends React.Component {
  render () {
    return (
      <div className="carousel">
        <ImageSlide url={ imgUrl } />
      </div>
    );
  }
}
Enter fullscreen mode Exit fullscreen mode

ImageSlideURL作为对象属性传递给组件props。本文稍后将介绍如何从用作引用的图像数组中正确获取图像 URL。

Arrow组件

const Arrow = ({ direction, clickFunction, glyph }) => (
  <div
    className={ `slide-arrow ${direction}` }
    onClick={ clickFunction }>
    { glyph }
  </div>
);
Enter fullscreen mode Exit fullscreen mode

这个组件更加简洁,因为我们无需在返回其标记之前进行任何设置。我决定在这里使用三个属性,因为这个组件同时用于左箭头和右箭头。因此,它的实现应该更加通用。第一个direction属性会告诉组件在每个实例(leftright)中使用哪个类。第二个属性clickFunction描述了点击每个箭头时应该发生什么,最后一个glyph属性则指向该组件的内容,也就是要渲染的内容。

接下来,我们将这两个箭头添加到Carousel组件中。

class Carousel extends React.Component {
  render () {
    return (
      <div className="carousel">
        <Arrow
          direction="left"
          clickFunction={ this.previousSlide }
          glyph="&#9664;" />

        <ImageSlide url={ imgUrl } />

        <Arrow
          direction="right"
          clickFunction={ this.nextSlide }
          glyph="&#9654;" />
      </div>
    );
  }
}
Enter fullscreen mode Exit fullscreen mode

由此我们可以更好地了解轮播图的最终定价。

接下来,我们应该回到Carousel组件部分,因为还有几件事需要完成。

你会注意到我们向Arrows 组件传递了两个不同的函数。它们负责处理幻灯片的过渡效果。但它们是如何实现的呢?

首先,我们需要了解需要创建哪些状态,才能告诉包装组件每次应该渲染哪张图片。所以,让我们来设置一个constructor函数,以便创建Carousel组件的初始状态。

class Carousel extends React.Component {
  constructor (props) {
    super(props);

    this.state = {
      currentImageIndex: 0
    };
  }

  render () {...}
}
Enter fullscreen mode Exit fullscreen mode

函数内部首先要做的constructor就是调用super()它,并将 props 作为参数传递,以便this在此上下文中通过关键字访问属性。目前,props由于构造函数中未使用 props,因此传递对象是可选的。

首先,我们设置一个名为currentImageIndex`set` 的状态0。该状态将保存每次需要在屏幕上渲染的图像的当前索引。这里我们从图像数组中的第一张图像开始。

我们将使用此状态来获取传递给ImageSlide组件的正确 URL。让我们看看如何实现。

class Carousel extends React.Component {
  constructor (props) {...}

  render () {
    return (
      <div className="carousel">
        <Arrow .../>

        <ImageSlide url={ imgUrls[this.state.currentImageIndex] } />

        <Arrow .../>
      </div>
    );
  }
}
Enter fullscreen mode Exit fullscreen mode

之后,我们只需要告诉组件如何根据用户交互更新状态。这项工作与我们的Arrow组件相关,由于我们已经传递了两个函数(` previousSlideand` 和 `or` nextSlide)作为属性,现在我们需要实现它们。

你会注意到这两个函数类似。它们的作用都是将currentImageIndex状态更新为 1,要么加 1,要么减 1。这里需要指出一点:有时我们需要重置当前索引的值,因为它最终会达到图像数组的最大或最小索引。因此,检查数组的长度非常重要,以便判断是否需要重置索引。

class Carousel extends React.Component {
  constructor (props) {...}

  previousSlide () {
    const lastIndex = imgUrls.length - 1;
    const { currentImageIndex } = this.state;
    const shouldResetIndex = currentImageIndex === 0;
    const index =  shouldResetIndex ? lastIndex : currentImageIndex - 1;

    this.setState({
      currentImageIndex: index
    });
  }

  nextSlide () {
    const lastIndex = imgUrls.length - 1;
    const { currentImageIndex } = this.state;
    const shouldResetIndex = currentImageIndex === lastIndex;
    const index =  shouldResetIndex ? 0 : currentImageIndex + 1;

    this.setState({
      currentImageIndex: index
    });
  }

  render () {...}
}
Enter fullscreen mode Exit fullscreen mode

对于该previousSlide函数,您可以注意到重置条件设置为状态为的情况currentImageIndex0这意味着如果索引指向数组中的第一张图像,然后用户单击左箭头,则索引应指向数组中的最后一张图像(imgUrls.length - 1)。

nextSlide作用基本相同,区别在于如果索引当前指向最后一张图片,则应将其重置为指向第一张图片(index = 0)。

在其余所有情况下,这两种方法都只是将上述状态改变 1,以获取上一张图片或下一张图片。

最后,还有一点需要注意。要更新 React 组件的状态,我们需要使用 `updateState`setState方法。这个方法负责告诉 React 它应该更新该组件及其子组件。这是更新用户界面的主要方式。

因此,每当您点击左箭头或右箭头时,您实际上就是在更新状态currentImageIndex,从而用新的图像幻灯片更新您的界面。

但是,为了this在这两个函数中访问关键字,您必须正确地将上下文绑定到它们。一种常见的方法是在组件的constructor方法中。

class Carousel extends React.Component {
  constructor (props) {
    ...

    this.nextSlide = this.nextSlide.bind(this);
    this.previousSlide = this.previousSlide.bind(this);
  }

  previousSlide () {...}

  nextSlide () {...}

  render () {...}
}
Enter fullscreen mode Exit fullscreen mode

最后,我们已经实现了轮播组件的所有逻辑。您可以在这个 CodePen 示例中查看运行演示和完整代码

PS1:由于这不是本文的目的,我省略了组件使用的样式,因此如果您对此感兴趣,应该查看上面提到的 codepen。

PS2:我仍然想给幻灯片过渡添加一些动画效果,但我希望用 React 的方式来正确地实现,所以这可能会另写一篇帖子 :)

感谢各位阅读!

文章来源:https://dev.to/willamesoares/how-to-build-an-image-carousel-with-react--24na