美文网首页RN 项目使用组件ReactNative 自定义组件
ReactNative 图片缓存(自定义组件、用于列表纯展示,不

ReactNative 图片缓存(自定义组件、用于列表纯展示,不

作者: 精神病患者link常 | 来源:发表于2019-10-31 17:06 被阅读0次

    涉及可更新的组件看着里 https://www.jianshu.com/p/f19b83e0ec33

    index.js

    import React, { Component, PureComponent } from 'react'
    import {
      View,
      Image,
      ImageBackground,
      Platform
    } from 'react-native'
    import styles from './style'
    import PropTypes from 'prop-types'
    import CacheUtil from './CacheUtil'
    import default_avatar from '../../Images/default_avatar.png'
    class CacheImage extends PureComponent {
      constructor(props) {
        super(props)
        this.state = {
          imagePath: undefined, // 图片的本地地址
        }
        this.cacheUtil = new CacheUtil(this.props.source)
      }
    
      async componentDidMount() {
        // this.props.source,先判断本地是否有缓存
        // 存在->  则返回本地路径,再赋值给state.imagePath
        // 没有->  则下载,下载完成后,返回本地路径,再赋值给state.imagePath
        let result = await this.cacheUtil.existImage()
        if (result.isHas) {
          this.setState({
            imagePath: Platform.OS ==='ios' ? result.imagePath : 'file://' + result.imagePath
          })
          console.log('本地图片');
        } else {
          this.cacheUtil.fetchImage((suc, imagPath) => {
            this.setState({
              imagePath: Platform.OS ==='ios' ? imagPath : 'file://' + imagPath
            })
          })
          console.log('网络下载');
        }
      }
    
      componentWillUnmount() {
        // 组件销毁,如果正在下载,则取消下载
        this.cacheUtil.cancelAxiosRequest()
        this.cacheUtil = null
      }
    
      render() {
        const { imageStyle, defaultSource } = this.props
        const { imagePath } = this.state
        return (
          <View>
            <ImageBackground
              source={defaultSource}
              style={[imageStyle, styles.backgroudStyle]}>
              {imagePath && <Image style={{ flex: 1, }} source={{ uri: imagePath }} />}
            </ImageBackground>
          </View>
        )
      }
    }
    
    CacheImage.propTypes = {
      source: PropTypes.string.require, // 图片url
      defaultSource: PropTypes.any, // 默认图片
      imageStyle: PropTypes.object, // 图片样式
      onPress: PropTypes.func, // 点击事件
    }
    CacheImage.defaultProps = {
      defaultSource: default_avatar       //默认图片
    }
    export default CacheImage
    
    

    style.js

    import { StyleSheet } from 'react-native'
    export default StyleSheet.create({
      backgroudStyle: {
        overflow:'hidden'
      }
    })
    
    

    CacheUtil.js

    import RNFS from 'react-native-fs';
    import CryptoJS  from 'crypto-js'
    import axios from 'axios'
    import Base64ToArraybuffer from 'base64-arraybuffer'
    import React, { Component } from 'react';
    
    export default class CacheUtil {
      constructor(imageURL){
        this.axiosFetchRequestCancel = null
        this.imageUrl = imageURL
      }
    
      /**
       * [existImage  判断图片是否存缓存]
       * imageUrl     [图片的网络路径]
       * @return      [返回是/否]
       */
      existImage = async ()=>{
        try {
          let imagePath = this.getImagePath(this.imageUrl)
          const result = await RNFS.exists(imagePath).catch(e => console.log('e',e))
          return {
            isHas: result,
            imagePath
          }
        } catch (e) {
          return {
            isHas: false,
          }
        }
      }
    
      /**
       * [getImagePath  获取图片的本地路径]
       * imageUrl       [图片的网络路径]
       * @return        [返回图片的本地路径]
       */
      getImagePath = ()=>{
        return this._getLocalPath(this.imageUrl) + this._getImageName(this.imageUrl)
      }
    
      /**
       * [fetchImage  下载图片]
       * imageUrl     [图片的网络路径]
       * @return      [返回图片的本地路径]
       */
      fetchImage = (callBack)=>{
        // 获取远端图片
        let that = this
        try {
          axios(this.imageUrl,
            {
              responseType: 'arraybuffer',
              cancelToken: new axios.CancelToken(function executor(c) {
              that.axiosFetchRequestCancel = c // 用于取消下载
            })
            }
          )
            .then(function(response) {
              let base64 = Base64ToArraybuffer.encode(response.data)
              let imagePath = that.getImagePath(that.imageUrl)
              that.axiosFetchRequestCancel = null
              RNFS.writeFile(imagePath, base64, 'base64').then(()=>{
                callBack && callBack(true, imagePath)
              }).catch(e=>{
                callBack && callBack(false)
              })
            }).catch(error=>{
              callBack && callBack(false)
            });
        } catch (e) {
        }
      }
    
      /**
       * [cancelAxiosRequest 取消axios post请求]
       */
      cancelAxiosRequest = ()=>{
        this.axiosFetchRequestCancel && this.axiosFetchRequestCancel('cancel')
      }
    
      /**
       * [getLocalPath 获取图片缓存的文件夹]
       */
      _getLocalPath = ()=>{
        return RNFS.DocumentDirectoryPath + '/Avatar/'
      }
    
      /**
       * [getImageSuffixName 获取图片的后缀名]
       */
      _getImageSuffixName = ()=>{
        let arr = this.imageUrl.split('.')
        return '.' + arr[arr.length - 1]
      }
    
      /**
       * [getImageMD5 获取图片MD5码,用于得到图片的本地名字]
       */
      _getImageMD5 = ()=>{
        return CryptoJS.MD5(this.imageUrl).toString()
      }
    
      /**
       * [getImageName 获取图片的完整名字]
       */
      _getImageName = ()=>{
        return this._getImageMD5(this.imageUrl) + this._getImageSuffixName(this.imageUrl)
      }
    
    }
    
    

    使用

    // 针对列表的数据,外部View一定要设置key,不然当列表数据改变时,会出现头像不正确问题~
    <View key = {item.userHeadUrl}>
      <CacheImage source={ item.userHeadUrl } />
    </View>
    

    相关文章

      网友评论

        本文标题:ReactNative 图片缓存(自定义组件、用于列表纯展示,不

        本文链接:https://www.haomeiwen.com/subject/piuymctx.html