在React中,封装组件是一种很常见的作法,可以提高代码的可复用性和可维护性。常见的组件封装有表单组件、模态框组件、通知组件、图片轮播图组件、下拉菜单组件等。
这时候就有人说不是有很多UI组件库吗?比如ElementUI、Ant Design等,为什么还要自己写呀?使用UI组件库确实是一种很好的选择,它提供了丰富的UI组件和工具,可以大大简化前端开发,然而,有时我们可能需要根据项目的具体需求进行一些自定义的组件封装,而不是仅仅局限于组件库提供的组件。
今天要写的是模态框组件。封装一个可复用的模态框组件,可以在不同的场景中使用,例如展示提示信息、确认操作等。
App.js文件:
import React, { useState } from "react";
import CommonModal from "./components/CommonModal";
//按需引入标签
import {Button} from 'antd';
/*
将父组件的状态传递给子组件,子组件检测数据变化进行状态更新,打开模态框,
点击取消或确定按钮之后又触发openModal函数的调用,并传递参数false,使parentModal状态发生变化,又传递给子组件进行关闭模态框
*/
function App() {
//定义变量进行传值
const [parentModal,setParentModal] = new useState(false);
const openModal = (data) => {
setParentModal(data);
}
return(
//点击按钮打开模态框
<>
<Button type="primary" onClick={openModal}>点我打卡</Button>
<CommonModal vis={parentModal} fn={openModal}></CommonModal>
</>
)
}
export default App;
CommonModal.jsx文件:
import { Modal } from 'antd';
import React,{useEffect, useState} from 'react'
function CommonModal(props) {
const [visible,setVisible] = useState(false);
//确认
const traggerComfirm = () => {
//调用父函数的方法
props.fn(false);
}
//取消
const traggerCancel = () => {
props.fn(false);
}
//监听数据是否发生变化
useEffect(() => {
setVisible(props.vis)
},[props.vis])
return (
<>
<div>
<Modal
open={visible}
onOk={traggerComfirm}
onCancel={traggerCancel}>
<p>1111111</p>
<p>1111111</p>
<p>1111111</p>
<p>1111111</p>
<p>1111111</p>
<p>1111111</p>
</Modal>
</div>
</>
)
}
export default CommonModal;
展示图:
但是它的逻辑有点繁琐,需要从父组件跳到子组件再跳到父组件…于是可以优化一下代码,这里用到了forwardRef和 useImperativeHandle。
React 使用 forwardRef 完成 ref 的转发。
useImperativeHandle可以让你在使用ref时自定义暴露给父组件的实例值
App.jsx文件:
import React, { useState ,useRef} from "react";
import CommonModal from "./components/CommonModal";
//按需引入标签
import {Button} from 'antd';
/*
将父组件的状态传递给子组件,子组件检测数据变化进行状态更新,打开模态框,
点击取消或确定按钮之后又触发openModal函数的调用,并传递参数false,使parentModal状态发生变化,又传递给子组件进行关闭模态框
*/
function App() {
const ModalRef = useRef(null);
//定义变量进行传值
const [parentModal,setParentModal] = new useState(false);
const openModal = (data) => {
// 获取具体DOM
console.log(ModalRef.current);
ModalRef.current.traggerOpen();
}
return(
//点击按钮打开模态框
<>
<Button type="primary" onClick={openModal} >点我打卡</Button>
<CommonModal ref={ModalRef}></CommonModal>
</>
)
}
export default App;
CommonModal.jsx文件:
import { Modal } from 'antd';
import React,{useEffect, useState, forwardRef, useImperativeHandle } from 'react'
function CommonModal(props,ref) {
const [visible,setVisible] = useState(false);
//确认
const traggerComfirm = () => {
//调用父函数的方法
// props.fn(false);
setVisible(false);
}
//取消
const traggerCancel = () => {
// props.fn(false);
setVisible(false);
}
const traggerOpen = () => {
setVisible(true);
}
useImperativeHandle(ref,() =>({
traggerOpen,
traggerComfirm,
traggerCancel,
}))
//监听数据是否发生变化
useEffect(() => {
setVisible(props.vis)
},[props.vis])
return (
<>
<div>
<Modal
open={props.visible}
onOk={traggerComfirm}
onCancel={traggerCancel}>
<p>1111111</p>
<p>1111111</p>
<p>1111111</p>
<p>1111111</p>
<p>1111111</p>
<p>1111111</p>
</Modal>
</div>
</>
)
}
export default forwardRef(CommonModal);