react子组件给父组件传参

981 阅读3分钟

因为react为单向数据流动,所以子组件给父组件传参需要在通过props. 总结:

子组件
interface AppProps {
  cropVisible: boolean;
  closeCrop: (e: any, type: number, data?: any, callback?: (data: any) => void) => void;
  currentjson: any;
}

// 子组件向父组件传参
onFinish = () => {
  const json = this.state.formjson;
  this.props.closeCrop(this, 1, json, (res: any) => {
    if (res) {
      this.initformData()
    }
  });
}

父组件
<Corpmod cropVisible={cropVisible} closeCrop={this.closeCrop} currentjson={currentjson}></Corpmod>

定义在父组件中的方法(给子组件调用)
closeCrop = (e: any, type: number, data: any, callback: any) => {
    this.setState(() => ({
      cropVisible: false
    }))
    if (type == 1) { // 确认
      const arr = JSON.parse(JSON.stringify(this.state.dataSource))
      arr.forEach((v: any) => {
        if (v.id === data.id) {
          v.osspicurl = data.osspicurl;
        }
      })
      this.setState({
        dataSource: arr
      }, () => {
        callback(true);
      })
    }
}

总结:子组件接受的是父组件传递过来的参数和方法,子组件通过调用父组件的方法向父组件传参数
  • 子组件 modal.tsx
import React from 'react';
import { Modal, Form, Input, Button, Select, Radio } from 'antd';
import input from 'antd/lib/input';
const { Option } = Select;

interface AppProps {
  cropVisible: boolean;
  closeCrop: (e: any, type: number, data?: any, callback?: (data: any) => void) => void;
  currentjson: any;
}
interface AppState { 
  formRef: any;
  formjson: any;
  seltypelist: any[];
}

class Corpmod extends React.Component<AppProps, AppState>
{
  constructor(props: AppProps) {
    super(props);

    this.state = {
      formRef: React.createRef(),
      formjson: {
        w: '', // 裁剪宽度
        h: '', // 裁剪高度
        x: '', // 裁剪起点横坐标
        y: '', // 裁剪起点纵坐标
        g: 'center', // 裁剪的原点位置
      },
      seltypelist: [
        {
          value: 'nw',
          text: '左上'
        },
        {
          value: 'north',
          text: '中上'
        },
        {
          value: 'ne',
          text: '右上'
        },
        {
          value: 'west',
          text: '左中'
        },
        {
          value: 'center',
          text: '中部'
        },
        {
          value: 'east',
          text: '右中'
        },
        {
          value: 'sw',
          text: '左下'
        },
        {
          value: 'south',
          text: '中下'
        },
        {
          value: 'se',
          text: '右下'
        }
      ]
    }
  }

  render() {
    const { cropVisible } = this.props;
    const { formRef, formjson, seltypelist } = this.state;
    return (
      <>
        <Modal title="裁剪" visible={ cropVisible } onCancel={ this.handleCancel } footer={ null }>
          <Form
            ref={formRef}
            initialValues={ formjson }
            labelCol={{ span: 8 }}
            wrapperCol={{ span: 16 }}
            onFinish={ this.onFinish }
            autoComplete="off"
          >
            <Form.Item
              label="裁剪宽度"
              name='w'
              // rules={[{ required: true }]}
            >
              <Input value={ formjson.w } allowClear onChange={ this.widthChange } />
            </Form.Item>
            <Form.Item
              label="裁剪高度"
              name='h'
            >
              <Input value={ formjson.h } allowClear onChange={ this.heightChange } />
            </Form.Item>
            <Form.Item
              label="裁剪起点横坐标"
              name='x'
            >
              <Input value={ formjson.x } allowClear onChange={ this.xChange } />
            </Form.Item>
            <Form.Item
              label="裁剪起点纵坐标"
              name='y'
            >
              <Input value={ formjson.y } allowClear onChange={ this.yChange } />
            </Form.Item>
            <Form.Item
              label="裁剪的原点位置"
              name='g'
            >
              <Select onChange={ this.gChange } value={ formjson.g }>
                {
                  (seltypelist || []).map((v: any) => {
                    return <Option value={v.value} key={v.value}>{v.text}</Option>
                  })
                }
              </Select>
            </Form.Item>
            <Form.Item wrapperCol={{ offset: 8, span: 16 }}>
              <Button type="primary" htmlType="submit" style={{marginRight: '10px'}}>确定</Button>
              <Button onClick={this.handleCancel}>取消</Button>
            </Form.Item>
          </Form>
        </Modal>
      </>
    )
  }

  splitObj = (obj: any) => {
    obj = JSON.stringify(obj);
    obj = obj.replace(/\{|\}|\'|\"+/g,'');
    let arr = obj.split(',');
    const newarr = [];
    for (var i = 0; i < arr.length; i++){
      if (arr[i].split(':')[1]) {
        newarr.push(arr[i]);
      }
    };
    for (var i = 0; i < newarr.length; i++){
      newarr[i] = newarr[i].replace(/\:/g,'_') + ',';
    };
    let str = newarr.join('');
    str = str.slice(0,str.length-1);
    str = str ? ',' + str : '';
    return str;
  }
  // 重置
  initformData = () => {
    // 初始化表单
    this.state.formRef.current!.setFieldsValue({
      w: '',
      h: '',
      x: '',
      y: '',
      g: 'center'
    });
    // 初始化react对象数据
    this.setState(() => ({
      formjson: {
        w: '',
        h: '',
        x: '',
        y: '',
        g: 'center'
      }
    }))
  }
  // 关闭弹窗
  handleCancel = () => {
    this.props.closeCrop(this, 2)
    this.initformData()
  }
  // 验证通过
  onFinish = () => {
    const json = this.state.formjson;
    let splitjson = this.splitObj(json);
    if (splitjson) {
      splitjson = '?x-oss-process=image/crop' + splitjson;
    }
    let url = this.props.currentjson.url + splitjson;
    const finallyjson = JSON.parse(JSON.stringify(this.props.currentjson))
    finallyjson.osspicurl = url;
    // console.log(finallyjson);
    this.props.closeCrop(this, 1, finallyjson, (res: any) => {
      if (res) {
        this.initformData()
      }
    });
  }
  widthChange = (e: any) => {
    const val = e.target.value;
    const formjson = this.state.formjson
    formjson.w = val;
    this.setState(() => ({
      formjson
    }))
  }
  xChange = (e: any) => {
    const val = e.target.value;
    const formjson = this.state.formjson
    formjson.x = val;
    this.setState(() => ({
      formjson
    }))
  }
  yChange = (e: any) => {
    const val = e.target.value;
    const formjson = this.state.formjson
    formjson.y = val;
    this.setState(() => ({
      formjson
    }))
  }
  gChange = (val: any) => {
    const formjson = this.state.formjson
    formjson.g = val;
    this.setState(() => ({
      formjson
    }))
  }
  heightChange = (e: any) => {
    const val = e.target.value;
    const formjson = JSON.parse(JSON.stringify(this.state.formjson))
    formjson.h = val;
    this.setState(() => ({
      formjson
    }))
  }
}

export default Corpmod
  • 父组件 Index.tsx
import styles from './index.less'
import React from 'react'
import { Button, Table, Image, message } from 'antd';
import axios from 'axios';
import ScaleMod from './components/scale'; // 缩放
import Watermark from './components/watermark'; // 水印
import Corpmod from './components/corpmod'; // 裁剪

const divStyle: React.CSSProperties = {
  marginTop: '10px'
};

interface AppProps { }
interface AppState {
  dataSource: any[];
  columns: any[];
  pagination: any;
  isScaleVisible: boolean;
  currentjson: object;
  watermaskVisible: boolean;
  cropVisible: boolean;
}
class OssPicSuffix extends React.Component<AppProps, AppState>
{
  constructor(props: AppProps) {
    super(props)

    this.state = {
      isScaleVisible: false, // 开启缩放
      currentjson: {}, // 当前选中项
      watermaskVisible: false, // 开启水印
      cropVisible: false, // 开启裁剪
      pagination: {
        current: 1,
        pageSize: 10,
        total: 0,
        pageSizeOptions: [10, 20, 30, 40, 50]
      },
      dataSource: [],
      columns: [
        {
          title: '原图片',
          dataIndex: 'url',
          render: (text: string, record: any) => {
            return (
              <>
                <div>
                  <Image
                    width={150}
                    height={150}
                    src={ text }
                  />
                </div>
                <div style={ divStyle }>
                  <a onClick={ this.copyUrl.bind(this, text) }>复制url</a>
                </div>
              </>
            )
          }
        },
        {
          title: '处理后图片',
          dataIndex: 'osspicurl',
          render: (text: string, record: any) => {
            return (
              <>
                <div>
                  <Image
                    width={150}
                    height={150}
                    src={ text }
                  />
                </div>
                <div style={ divStyle }>
                  <a onClick={ this.copyUrl.bind(this, text) }>复制url</a>
                </div>
              </>
            )
          }
        },
        // {
        //   title: '处理后地址',
        //   dataIndex: 'osspicurl'
        // },
        {
          title: '操作',
          dataIndex: 'options',
          render: (text: string, record: any) => {
            return (
              <>
                <Button type="primary" style={{ marginRight: '10px' }} onClick={this.showScaleModal.bind(this, record)}>缩放</Button>
                <Button type="primary" style={{ marginRight: '10px' }} onClick={this.watermarkshow.bind(this, record)}>设置水印</Button>
                <Button type="primary" style={{ marginRight: '10px' }} onClick={this.watercropshow.bind(this, record)}>裁剪</Button>
              </>
            )
          }
        }
      ]
    }
    this.changepagination = this.changepagination.bind(this);
    this.closeWater = this.closeWater.bind(this);
  }

  render() {
    const {
      isScaleVisible,
      currentjson,
      dataSource,
      columns,
      pagination,
      watermaskVisible,
      cropVisible
    } = this.state;
    return (
      <div style={{ padding: '10px 30px' }}>
        <h3 style={{ fontSize: '20px', display: 'flex', alignItems: 'center'}}>
          <span>oss图片后缀处理</span>
        </h3>
        <Table bordered dataSource={ dataSource } columns={ columns } pagination={ pagination } onChange={this.changepagination}/>
        <ScaleMod isScaleVisible={isScaleVisible} currentjson={currentjson} closeSacle={this.closeSacle}></ScaleMod>
        <Watermark watermaskVisible={watermaskVisible} closeWater={this.closeWater} currentjson={currentjson}></Watermark>
        <Corpmod cropVisible={cropVisible} closeCrop={this.closeCrop} currentjson={currentjson}></Corpmod>
      </div>
    )
  }
  
  // 复制
  copyUrl = (val: string) => {
    const input = document.createElement('input');
    document.body.appendChild(input);
    input.setAttribute('value', val);
    input.select();
    if (document.execCommand('copy')) {
      message.success('复制成功!');
    }
    document.body.removeChild(input);
  }
  // 改变页数
  changepagination = (page: any, pageSize: any) => {
    // console.log(page)
    const pagejson = JSON.parse(JSON.stringify(this.state.pagination));
    if (pagejson.pageSize !== page.pageSize) {
      pagejson.current = 1;
    } else {
      pagejson.current = page.current;
    };
    pagejson.pageSize = page.pageSize
    this.setState({
      pagination: pagejson
    }, () => {
      this.getData()
    })
  }
  getData = () => {
    const { 
      current,
      pageSize
    }: any = this.state.pagination;
    axios({
      url: `http://127.0.0.1:7001/oss/get.oss.list?pageNo=${current}&pageSize=${pageSize}`,
      method: 'GET'
    }).then(res => {
      const list = (res.data.data.list || []).map((v: any, i: number) => {
        v.key = i;
        v.osspicurl = v.url;
        return v;
      })
      const pagejson = JSON.parse(JSON.stringify(this.state.pagination));
      pagejson.total = res.data.data.count;
      this.setState(() => ({
        dataSource: list,
        pagination: pagejson
      }))
    })
  }
  // 开启缩放
  showScaleModal = (data: any) => {
    this.setState(() => ({
      isScaleVisible: true,
      currentjson: data
    }))
  }
  // 关闭缩放
  closeSacle = (e: any, type: number, data: any, callback: any) => {
    this.setState(() => ({
      isScaleVisible: false
    }))
    if (type === 1) { // 确认
      const arr = JSON.parse(JSON.stringify(this.state.dataSource))
      arr.forEach((v: any) => {
        if (v.id === data.id) {
          v.osspicurl = data.osspicurl;
        }
      })
      this.setState({
        dataSource: arr
      }, () => {
        callback(true);
      })
    }
  }
  // 开启水印
  watermarkshow = (data: any) => {
    this.setState(() => ({
      watermaskVisible: true,
      currentjson: data
    }))
  }
  // 关闭水印
  closeWater = (e: any, type: number, data: any, callback: any) => {
    this.setState(() => ({
      watermaskVisible: false
    }))
    if (type === 1) { // 确认
      const arr = JSON.parse(JSON.stringify(this.state.dataSource))
      arr.forEach((v: any) => {
        if (v.id === data.id) {
          v.osspicurl = data.osspicurl;
        }
      })
      this.setState({
        dataSource: arr
      }, () => {
        callback(true);
      })
    }
  }
  // 开启裁剪
  watercropshow = (data: any) => {
    this.setState(() => ({
      cropVisible: true,
      currentjson: data
    }))
  }
  // 关闭裁剪
  closeCrop = (e: any, type: number, data: any, callback: any) => {
    this.setState(() => ({
      cropVisible: false
    }))
    if (type == 1) { // 确认
      const arr = JSON.parse(JSON.stringify(this.state.dataSource))
      arr.forEach((v: any) => {
        if (v.id === data.id) {
          v.osspicurl = data.osspicurl;
        }
      })
      this.setState({
        dataSource: arr
      }, () => {
        callback(true);
      })
    }
  }

  componentDidMount() {
    this.getData()
  }
}

export default OssPicSuffix