当前位置: 首页 > Web前端 > HTML5

组件实战系列——一、使用React实现一个Collapse组件

时间:2023-04-04 23:12:13 HTML5

编写组件的能力是衡量前端工程师水平的重要指标,无论是基础组件还是业务组件。作者还喜欢在空闲时间编写组件。为了帮助初学者手写React组件,也为了分享自己写组件的心得和想法,我决定开一个系列,即:组件实战系列,分享一些公共组件和组件的实现方法和实现技巧业务组件。作为本系列的第一篇文章,我来分享一下如何从零到一个实现一个折叠面板(Collapse)组件。Collapse基本UI将Collapse面板绘制为基本组件。可折叠区域,单击标题区域可折叠和展开内容区域。为了组件的美观,可以在标题右侧添加一个箭头图标,以便在展开和折叠时旋转它。为了降低环境搭建成本,实际使用了create-react-app环境。创建一个create-react-app开发环境非常简单。你只需要在安装node的系统中执行如下命令npxcreate-react-app项目名。名称必须是英文,create-react-app会自动为我们创建一个目录。项目创建完成后,在src目录下创建一个名为Collapse.jsx的文件,输入以下代码:(初学者可以选择复制)importReact,{useState}from"react";import"./style.css";constCollapsablePanel=()=>{const[isCollapsed,setIsCollapsed]=useState(true);consttogglePanel=()=>{setIsCollapsed((prevState)=>!prevState);};返回(25px"viewBox="0010241024"style={{color:'#6495ed'}}>

div>);};导出默认CollapsablePanel;239,239);padding-top:40vh;}.pannel{width:400px;text-align:left;}.heading{background-color:#bfa;边框顶部-lborder-top-right-radius:10px;颜色:#000;字体大小:20px;行高:20px;border:1pxsolidrgb(212,240,205);;显示:弹性;对齐项目:居中;证明内容:空格之间;cursor:pointer;}.content{字体大小:20px;背景:#fff;边框:1px实心#fff;边框顶部:无;填充:020px;颜色:#000000;overflow:hidden;}.contentInner{padding:20px0;}创建完以上两个文件后,在index.js中挂载创建的Collapse组件:(原代码无所谓,删除即可)importReactfrom'react';从'react-dom/client'导入ReactDOM;从'./components/Collapse'导入Collapse;constroot=ReactDOM.createRoot(document.getElementById('root'));root.render(<折叠/>);创建完成后,使用yarnstart命令启动应用,可以看到绘制的Collapse组件的外观:Collapse的基本UI绘制完成,回顾一下都做了哪些操作:首先是一个状态定义namedisCollapsed用于存储组件的展开和关闭状态,声明了一个名为togglePanel的方法,当用户点击标题时可以调用该方法实现面板的展开和关闭。然后,命名pannel、heading、contentdiv容器及其相关子容器的样式,并在style.css中设置容器的样式。组件中的ICON直接使用svg标签绘制,避免引入svg包导致组件体积变大。有很多方法可以在内容区域中实现动画。可以使用css的transition属性,也可以使用React生态中的各种动画库。在React生态中,有一个非常流行的动画库叫react-spring,它不仅功能强大,还支持hook调用。本文使用这个动画库来实现内容区域展开动画和按钮旋转动画。安装react-spring动画库yarnaddreact-spring安装完react-spring动画库后,可以定义一个方法让spring帮我们生成动画样式constpanelContentAnimatedStyle=useSpring({height:isCollapsed?0:200,});然后将内容区的标签名从
改为(和useSpring一样,animated也是react-spring的一个对象),添加新建的panelContentAnimatedStyle:importReact,{useState}from"react";import{useSpring,animated}from"react-spring";import"./style.css";constCollapsablePanel=()=>{const[isCollapsed,setIsCollapsed]=useState(true);consttogglePanel=()=>{setIsCollapsed((prevState)=>!prevState);};constpanelContentAnimatedStyle=useSpring({height:isCollapsed?0:180,});返回(;/span>
);};导出默认的CollapsablePanel;点击标题栏可以看到如下效果:等等~~高度固定了吗??很明显不是!用户在使用Collapse组件时,传递的内容不仅是文本,还可以是图片或者任何类型的ReactNode,所以展开时需要获取内容对象的实际高度。有一个获取DOM对象高度的库帮帮忙,react-use-measure,这个库不仅可以测量DOM对象的长宽,还可以测量DOM对象从上、下、左的位置,和浏览器的权利。react-use-measure提供了一个叫useMeasure的hook,使用方法如下:const[ref,bounds]=useMeasure();第一个参数是ref对象,绑定到待测DOM对象的ref属性上即可,第二个bounds是location对象,包括上面提到的所有属性。继续修改组件代码Collapse.jsx:importReact,{useState}from"react";import{useSpring,animated}from"react-spring";importuseMeasurefrom'react-use-measure'import"./style.css";constCollapsablePanel=()=>{const[isCollapsed,setIsCollapsed]=useState(true);const[ref,bounds]=useMeasure();consttogglePanel=()=>{setIsCollapsed((prevState)=>!prevState);};constpanelContentAnimatedStyle=useSpring({height:isCollapsed?0:bounds.height,});返回(25px"viewBox="0010241024"style={{color:'#6495ed'}}>让痛苦本身变大,让它安定下来吧痛苦的事情很棒,但这是一次院子出售。客户自己,客户才能追求公司的发展。好像我要打开它们quedesertexpeditasitaccusamussuntlaudantiumrepellendusnisi!坐下,结果。Tempora,officiismolestiaefugasitquaeliquidmaxime。);};导出默认的CollapsablePanel;目前效果:使用react-use-measure可以轻松获取DOM对象的真实高度及其在浏览器中的位置。在项目中灵活使用可以提高开发效率,实现箭头图标旋转动画和箭头图标与内容区域的旋转。实现方式类似,只是将其label改为animated.div,绑定useSpring生成的style对象即可。生成箭头ICON旋转动画样式对象:consttoggleWrapperAnimatedStyle=useSpring({transform:isCollapsed?"rotate(0deg)":"rotate(180deg)",});svg对象包装一个div,并绑定动画样式:importReact,{useState}from"react";import{useSpring,animated}from"react-spring";importuseMeasurefrom'react-use-measure'import"./style.css";constCollapsablePanel=()=>{const[isCollapsed,setIsCollapsed]=useState(true);const[ref,bounds]=useMeasure();consttogglePanel=()=>{setIsCollapsed((prevState)=>!prevState);};constpanelContentAnimatedStyle=useSpring({height:isCollapsed?0:bounds.height,});consttoggleWrapperAnimatedStyle=useSpring({transform:isCollapsed?"rotate(0deg)":"rotate(180deg)",});返回(折叠花Loremipsumdolorsitamet,consetetursadipscingelitr,seddiamnonumyeirmodtemporinviduntutlaboreetdoloremagnaaliquyamerat,seddiamvoluptua.);};导出默认的CollapsablePanel;可以看到如下效果:总结动手实践组件系列的第一篇文章。上手组件系列的第一篇之所以讲Collapse组件的实现,是因为这个组件的实现简单有趣。你可以通过阅读体验编写组件的乐趣。一个简单的组件在实现的时候也可能会遇到问题,比如如何获取内容区域的高度,这个很有代表性。目前React和Vue的生态异常繁荣。开发者在实现特定需求时,应该能够灵活地使用这些开源库来开发简单而强大的组件。Coollapse.jsx源码style.css源码