摘要:组件实现基本简介类似于实现的组件,首先基本结构分析遮罩层内容包装层主体内容层,包含固定定位布局,全屏遮盖显示,所以内容自定义实现功能目标两种调用方式一些内容遮罩层和的显示与否,单击是否可关闭其他必备功能结构布局攻克基本布局遮
Madal组件实现基本简介
类似于antd实现的modal组件,首先基本结构分析:
modal-mask遮罩层
modal-warp内容包装层
modal主体内容层,包含:title、content、footer、close-btn
固定定位布局,全屏遮盖显示,所以内容自定义
实现功能目标:
两种调用方式
遮罩层、footer和close-btn的显示与否,单击是否可关闭
其他必备功能
结构布局攻克基本布局
// 遮罩层需要实现全屏遮罩 // 内容层高度可自定义// 右上角关闭按钮+} // 主内容//title标题//body用户输入内容{title}{children}// footer底部按钮
遮罩层全屏覆盖
position: fixed定位
全屏实现
top: 0; right: 0; bottom: 0; left: 0; z-index: 1000;
内容层
position: fixed定位(modal-warp层)
warp层的布局大小考虑
全屏:如果warp层实现全屏,由于和mask层为兄弟组件,导致warp层位于mask层之上,后面对mask层单击可关闭功能易出现单击不到,因为被全屏的warp层遮挡(可考虑使用事件委托,将单击事件绑定至第一个父组件,通过判断去除modal层的单击,虽然单击的还是warp层);
大小跟随modal层:及设置warp层的大小刚好为其内容modal,这样就不会覆盖全部mask层,但是,后期对传入设置是否显示mask层的功能有所影响(因为warp层不全屏,如果mask设置不显示,会导致用户可以操作到底下主内容),可考虑mask的显隐通过visibility: hidden控制.
基本对外接口(函数式)
const Modal = ({ visible=false, style, width= 520, zIndex=1000, centered=false, title="title", footer, wrapClassName="", okText="确定", okType="primary", cancelText="取消", cancelType="default", closable= true, onOk=() => {}, onCancel=() => {}, mask=true, maskClosable= true, children="Basic body" }) => { return ( visible ? ReactDOM.createPortal(....,document.querySelector("body")) : null ) }
组件采用函数无状态编程,Modal的显隐由外部控制,内部不控制;
组件的挂载使用ReactDOM.createPortal(child,container)挂载至body
基本使用形式
import React,{ PureComponent } from "react"; import { Modal,Button } from "lwh_react"; export default class baseModal extends PureComponent { state = { visible: false } showModal = () => { this.setState({ visible: true }) } onCancel = () => { console.log("cancel") this.setState({ visible: false }) } onOk = () => { console.log("ok") this.setState({ visible: false }) } render() { const { visible } = this.state; return (简单基本用法:) } } modal提示内容
效果
如何实现类似antd中modal.method的方法调用弹窗形式(且调用后返回一个引用包含{update, destroy}可控制弹窗):
Modal.info({...})
Modal.success({...})
Modal.error({...})
Modal.warning({...})
Modal.confirm({...})
method()是Modal的方法即先给组件Modal增加对应方法,返回一个对象;
通过在method(props)方法中将其方法参数作为组件Modal的props传入,并render(Modal);
需要返回一个对象包含{update, destroy}基本代码如下:
["confirm","info","success","error","warning"].forEach(item => { // eslint-disable-next-line react/no-multi-comp Modal[item] = ({ ...props}) => { let div = document.createElement("div"); let currentConfig = Object.assign({}, props); document.body.appendChild(div); // 使用高阶组件剔除Method()调用形式不可配置的props和默认值 const FunModal = HOCModal(Modal); // 关闭 const destroy = () => { const unmountResult = ReactDOM.unmountComponentAtNode(div); if (unmountResult && div.parentNode) { div.parentNode.removeChild(div); } } const render = (config) => { //name传入调用的方法名,用于区分使用不同footer和Icon ReactDOM.render(, div); } // 更新 const update = (newConfig) => { currentConfig = Object.assign({}, currentConfig,newConfig); render(currentConfig); } render(currentConfig); return { destroy: destroy, update: update } } });
因为Modal.method()调用形式可使用的配置props与
如Modal.confirm({})中不可配置footer;Modal.info({})的footer底部默认应该为一个button,且默认值为我知道了;
再如Modal.method()不需要传递visible,而
再比如Modal.method()中没有children,而使用content作为内容的传递,所以需要适配下;
所以这里考虑使用一个高阶组件HocModal对传给Modal的props进行部分剔除和默认值修改
const HOCModal = (Component) => { //剔除出visible,footer,closable,使其不可配,赋予永久默认值 return ({ visible, footer, closable, okText="知道了", okType="primary", onOk=() => {}, onCancel=() => {}, maskClosable= false, content="Basic body", name, destroy, ...props }) => { // 修改onOk方法传入关闭Modal方法destroy(); const onOk_1 = () => { onOk(); destroy(); } // 修改onCancel方法传入关闭Modal方法destroy(); const onCancel_1 = () => { onCancel(); destroy(); } // Modal底部footer固定使用这里为默认值,且不可自定义footer,如果调用的是confirm返回undefined走Modal的默认配置,其他则只显示一个OK、button // eslint-disable-next-line react/no-multi-comp const Footer = () => ( name == "confirm" ? undefined : ) return () } }
使用测试
const ModalConfirm = () => { const onInfo = () => { Modal.info({ title: "Info", content: (), onOk() {} }); } const showDeleteConfirm = () => { const modal = Modal.confirm({ title: "你确定需要删除该项么?", content: "一些删除提示内容", okText: "删除", okType: "danger", cancelText: "取消", onOk() { console.log("OK"); }, onCancel() { console.log("Cancel"); } }); console.log(modal); } return (some messages...some messages...
some messages...some messages...
) }
结果展示
其他优化显隐的动画过渡;
组件的保留,这里只实现了关闭即摧毁;优化为可选择不摧毁只是隐藏;
支持异步加载关闭
“积跬步、行千里”—— 持续更新中~,喜欢的话留下个赞和关注哦!
往期经典好文:
你不知道的CORS跨域资源共享
性能优化篇---Webpack构建速度优化
团队合作必备的Git操作
使用pm2部署node生产环境
下期考虑Carousel走马灯封装
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/54727.html
摘要:组件实现基本简介类似于实现的组件,首先基本结构分析遮罩层内容包装层主体内容层,包含固定定位布局,全屏遮盖显示,所以内容自定义实现功能目标两种调用方式一些内容遮罩层和的显示与否,单击是否可关闭其他必备功能结构布局攻克基本布局遮 Madal组件实现基本简介 showImg(https://segmentfault.com/img/bVbqhvl?w=1848&h=834); 类似于an...
摘要:声明式用法只需使用动画的名称,该动画将在加载该元素时立即生效。实际案例这个库支持本地推送通知功能比较全面。实际案例具有缩放支持,回调,缩放以适应和滚动指示器支持的组件。这是图像上传或图像处理的基本库。 本篇 React native 库列表不是从网上随便找的, 这些是我在我的应用中亲自使用的库。 这些库功能可能跟其它库也有,但经过大量研究并在我的程序中尝试后,我选择了这些库。 想阅读更...
摘要:本文是造轮系列第二篇。实现方式事件处理跟差不多,唯一多了一步就是当点击或者的时候,如果外部有回调就需要调用对应的回调函数。 本文是React造轮系列第二篇。 1.React 造轮子系列:Icon 组件思路 本轮子是通过 React + TypeScript + Webpack 搭建的,至于环境的搭建这边就不在细说了,自己动手谷歌吧。当然可以参考我的源码。 想阅读更多优质文章请猛戳Git...
摘要:系统架构介绍本项目开发基于框架,利用进行模块化构建,前端编写语言是,利用进行转换。单页是为单页应用量身定做的你可以把拆成很多,这些由路由来加载。前者用来获取的状态,后者用来修改的状态。 系统架构介绍 本项目开发基于 React + Redux + React-Route 框架,利用 webpack 进行模块化构建,前端编写语言是 JavaScript ES6,利用 babel进行转换。...
阅读 1095·2021-11-16 11:42
阅读 2881·2021-10-12 10:18
阅读 2838·2021-09-24 09:48
阅读 3436·2019-08-30 15:56
阅读 1498·2019-08-30 14:17
阅读 3026·2019-08-29 12:14
阅读 886·2019-08-27 10:51
阅读 1998·2019-08-26 13:28