React 组件图片库的延迟加载

React 组件图片库的延迟加载

原文地址:http://andrewhfarmer.com/react-image-gallery/
水平有限,有误的地方请指正

  • 事实证明,用react建立一个 带有延迟加载效果的图片库 非常容易,
    这里是一个单页面的组件 仅仅只有70行代码 包含 空行 和 注释
  • 我将带你 一步一步 的建立这个图片库的组件,当你跟着写完,就会学会啦

项目准备

  • 如果你不知道如何启动一个react项目,没关系,下载我的项目,克隆一份到本地
    就可以啦。
    git clone https://github.com/ahfarmer/minimal-react-starter.git
    cd minimal-react-starter
    npm install
    npm start
  • 这项目文件有个 单一的 HelloWorld 组件,你完全可以动手编辑这个文件(HelloWorld.js)
    跟着我写项目的其余的部分,当你保存修改的时候,浏览器会自动刷新。

图库步骤

  • 1.首先,我将写一个新的组件 起个名字 定义一个 属性(propTypes);
import React from 'react';

    //组件名称一定要大写
class Gallery extends React.Component {
  // 效果代码写在这里
}
Gallery.propTypes = {
  imageUrls: React.PropTypes.arrayOf(React.PropTypes.string).isRequired,
};
export default Gallery; //导出图库

这里 只用到一个属性:一个 imgUrl(图片路径) 的【数组】!!!

    正确的使用 React PropTypes(定义属性的类型) 能够节省大量的调试时间,
    比如,你的图库组件传递的不是字符串数组,
    那么,控制台就清晰的看到 警告提示性的文字。
    不要省略 React.PropTypes.object or React.PropTypes.any!!!
  • 2.我们写一一些图片地址到 组件中(index.js)
import React from 'react';
import ReactDOM from 'react-dom';
import Gallery from './Gallery';

let urls = [
  '/react-image-gallery/img/cat1.jpg',
  '/react-image-gallery/img/cat2.jpg',
  '/react-image-gallery/img/cat3.jpg',
];

ReactDOM.render(
  <Gallery imageUrls={urls}/>,
  document.getElementById('mount')
);

如果你不喜欢这些 小猫的图片,可以替换成你喜欢的美图,
添加多少张都行

图库的渲染

  • 1.到目前为止,还不能显示出来,我们要编译一下render()中的代码
import React from 'react';

class Gallery extends React.Component {
  renderImage(imageUrl) {
    return (
      <div>
        <img src={imageUrl} />
      </div>
    );
  }

  render() {
    return (
      <div className="gallery">
        <div className="images">
          {this.props.imageUrls.map(imageUrl => this.renderImage(imageUrl))}
        </div>
      </div>
    );
  }
}
// 定义属性值的类型 必须为 字符串组成的数组
Gallery.propTypes = {
  imageUrls: React.PropTypes.arrayOf(React.PropTypes.string).isRequired,
};
export default Gallery;

我的代码都尽量用最新的语法(最简洁和可读的 es6)

    1. ok,我会用2种方式,在render()中用 div 包裹 调用 renderImage 每次加载一个 imgurl(图片地址)
      我们将使用 es中的 Array.prototype.map() 来生成数组类型的dom节点

添加延迟图片

  • 如果图片已经加载成功,如果没有 旋转加载的小图标,用户看到空白的图片效果很糟糕,所以接下来我们就添加
    小图标, 只需要4步

1.添加状态state

- 首先,组件需要跟踪 图片加载的 状态,显示默认为小图标。
- 在 cunstructor中设置默认状态,默认为true,当组件第一次渲染成功时候就加载图片。
constructor(props) {
  super(props);
  this.state = {
    loading: true,
  };
}

2.显示小图标

- 当图片的状态为加载中时,就显示。
- 创建一个 图片加载的方法 randerSpinner()
- 在你的 rnder() 方法中调用它就可以了
//封装 图片正在加载:
renderSpinner() {
  if (!this.state.loading) {
    // Render nothing if not loading 
    return null;
  }
  return (
    <span className="spinner" />
  );
}

// render()中的代码为:
render() {
  return (
    <div className="gallery">
      {this.renderSpinner()}
      <div className="images">
        {this.props.imageUrls.map(imageUrl => this.renderImage(imageUrl))}
      </div>
    </div>
  );
}

此时,你会在页面中看到图标一直在加载。。。

3.通过onLoad 和 onError 来加载

  • 接下来我们将添加 onload 和 onError 事件来监控图片加载成功获至失败
  • 添加这些属性到你的图片标签上
  • onload = {this.handleStateChange.bind(this)}
    onError = {this.handleStateChange.bind(this)}

  • 添加 事件到组件中

handleStateChange() {
  // In React 0.13 use: 'this.refs.gallery.getDOMNode()' 
  const galleryElement = this.refs.gallery;
  this.setState({
    loading: !imagesLoaded(galleryElement),
  });
}

接下来 我们要 写一个 imageLoader() 方法,括号中接收一个参数,当加载成功,返回一个true.
获取图库 元素的DOM节点 的用ref ,在 render()中写入就可以啦.

<div className="gallery" ref="gallery">

获取。用 this.refs.gallery

4.检测所有的图片是否加载完成

imageLoader()方法 不依赖任何组件,所有我们直接在组件外部定义它就好了。

function imagesLoaded(parentNode) {
  const imgElements = parentNode.querySelectorAll('img');
  for (const img of imgElements) {
    if (!img.complete) {
      return false;
    }
  }
  return true;
}

完整的代码

import React from 'react';

/**
 * Given a DOM element, searches it for <img> tags and checks if all of them
 * have finished loading or not.
 * @param  {Element} parentNode
 * @return {Boolean}
 */
function imagesLoaded(parentNode) {
  const imgElements = parentNode.querySelectorAll('img');
  for (const img of imgElements) {
    if (!img.complete) {
      return false;
    }
  }
  return true;
}

class Gallery extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      loading: true,
    };
  }

  handleImageChange() {
    // In React 0.13 use: 'this.refs.gallery.getDOMNode()' 
    const galleryElement = this.refs.gallery;
    this.setState({
      loading: !imagesLoaded(galleryElement),
    });
  }

  renderSpinner() {
    if (!this.state.loading) {
      return null;
    }
    return (
      <span className="spinner" />
    );
  }

  renderImage(imageUrl) {
    return (
      <div>
        <img
          src={imageUrl}
          onLoad={this.handleImageChange.bind(this)}
          onError={this.handleImageChange.bind(this)}
          />
      </div>
    );
  }

  render() {
    return (
      <div className="gallery" ref="gallery">
        {this.renderSpinner()}
        <div className="images">
          {this.props.imageUrls.map(imageUrl => this.renderImage(imageUrl))}
        </div>
      </div>
    );
  }
}
Gallery.propTypes = {
  imageUrls: React.PropTypes.arrayOf(React.PropTypes.string).isRequired,
};
export default Gallery;
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值