【图片预览】第三种方式:将组件数据放在公共状态下

背景:考虑到项目中很多页面都需要图片查看器,每个页面都去引入ImgViewer组件有点麻烦,现在将ImgViewer组件放在公共状态下

 

1、models/imgViewer.ts

import { Reducer } from 'umi'

export interface ImgViewerModelState {
  visible?: boolean // 显示隐藏,默认:false
  images: Array<object> // 图片列表,必传,格式:[{ alt: '', src: '', downloadUrl: '' }]
  activeIndex?: number // 当前展示图片的下标,默认:0
  downloadable?: boolean // 是否支持下载,默认:true
}

interface ImgViewerType {
  namespace: 'imgViewer'
  state: ImgViewerModelState
  reducers: {
    setState: Reducer<ImgViewerModelState>
  }
}

const ImgViewerModel: ImgViewerType = {
  namespace: 'imgViewer',
  state: { visible: false, images: [], activeIndex: 0, downloadable: true },
  reducers: {
    /*
      调用setState时,
        如果visible为false,其他参数不用传,用默认的值
        如果visible为true,images必传,visible和downloadable为true,可不传,activeIndex一般需要传
    */
    setState(state, { visible = true, images = [], activeIndex = 0, downloadable = true }): ImgViewerModelState {
      return { visible, images, activeIndex, downloadable }
    }
  }
}

export default ImgViewerModel

 

2、models/connect.d.ts

  引入imgViewer模块

    import type { ImgViewerModelState } from './imgViewer'

  暴露出去

    export interface ConnectState {
      imgViewer: ImgViewerModelState
    }

 

3、ImgViewer/index.tsx

import React from 'react'
import Viewer from 'react-viewer'
import { connect } from 'umi'
import './index.less'

const ImgViewer: React.FC = (props: any) => {
  const { visible, images, activeIndex = 0, downloadable = true, dispatch } = props

  const handleClose = () => dispatch({ type: 'imgViewer/setState', visible: false })

  return (
    <Viewer
      visible={visible}
      images={images}
      activeIndex={activeIndex}
      onClose={handleClose}
      onMaskClick={handleClose} // 点击遮罩关闭
      downloadable={downloadable} // 是否显示下载按钮,默认显示,显示时imgs对象中需要有downloadUrl字段
      downloadInNewWindow // 新窗口打开图片
    />
  )
}

export default connect()(ImgViewer)

  index.less

.react-viewer {
  position: absolute;
  z-index: 10000;
}

 

4、BasicLayout.tsx关键代码

import { ImgViewerModelState } from 'umi' // 引入umi中的ImgViewerModelState接口
import { ConnectState } from '@/models/connect' // 引入ConnectState将当前组件编程高阶组件
import ImgViewer from '@/components/ImgViewer' // 引入组件

// 接口中指明imgViewer的指向,否则从props中解构会报红
interface BasicLayoutProps {
  imgViewer: ImgViewerModelState
}

const BasicLayout: React.FC<BasicLayoutProps> = (props) => {
  const { imgViewer: { visible, images, activeIndex, downloadable } } = props  // 图片查看器的状态

  return (
    <ProLayout>
      <ImgViewer
        visible={visible as boolean}
        images={images as Array<object>}
        activeIndex={activeIndex}
        downloadable={downloadable}
      />
    </ProLayout>
  )
}

// 添加imgViewer
export default connect(({ global, settings, night, imgViewer }: ConnectState) => ({
  collapsed: global.collapsed,
  settings,
  night,
  imgViewer
}))(BasicLayout)

 

5、使用

import { connect, Dispatch } from 'umi' // 引入connect和Dispatch

// 接口中定义dispatch
interface PropsType {
  dispatch: Dispatch
}

  // 图片预览的回调中通过dispatch去修改公共状态
  const handleImgPreview = (list: Array<any>, activeIndex: number) => {
    const { dispatch } = props
    const images: Array<object> = list.map(({ alt, src }) => ({ alt, src, downloadUrl: src }))
    dispatch({ type: 'imgViewer/setVisible', images, activeIndex })
  }

export default connect()(Content) // 导出时改为高阶组件

 

posted @ 2022-03-11 11:01  吴小明-  阅读(96)  评论(0编辑  收藏  举报