react实现移动端下拉菜单的示例代码
前言
项目中要实现类似与vant的DropdownMenu:下拉菜单。看了vans的效果其实也没什么难度,于是动手鲁了一个这样的组件。
项目的技术栈为react全家桶+materialUI+antDesignmobile。
vans的效果
我自己实现的效果
思路
常规做法获取dom元素,动态修改选中dom的innerHtml。
当然这种方式不是react推荐的
我的做法既然react不推荐直接操作dom元素,那可以采用动态动态修改class的方式达到效果,例如:
letcls="normal" div未被选中时div被选中时 cls+="current"
实现步骤
顶部tab采用三个div的方式布局,由于需要动态修改tab上的标题,所以定义一个数组,reducer中的tab数据结构如下
lettabs={}; tabs[TABKAY.AREA]={ key:TABKAY.AREA, text:"全部区域", obj:{} }; tabs[TABKAY.SORT]={ key:TABKAY.SORT, text:"综合排序", obj:{} }; tabs[TABKAY.FILTER]={ key:TABKAY.FILTER, text:"筛选", obj:SX }; constinitialState={ areas:[{id:"",name:"全部区域"}], tabs:tabs, actionKey:TABKAY.AREA,//标识了当前选中tab closePanel:true//标识paneldiv是否显示 };
tabUI组件的页面容器渲染方法
renderTabs(){ const{tabs,actionKey,closePanel}=this.props; //--------- if(!closePanel){ fixedBody(); }else{ looseBody(); } //--------- letaray=[]; for(letkeyintabs){ letitem=tabs[key]; letcls=item.key+"item"; if(item.key===actionKey&&!closePanel){ cls+="current"; } aray.push(this.onChangeTab(item.key)}> {item.text}
样式:这里边有个技巧,就是利用了css元素选择器的伪类的方式巧妙实现了箭头以及箭头的旋转动画
.item{ flex:1; font-size:15px; border-right:0.5pxsolid#eaeaea; text-align:center; &:last-child{ border:none; } &.AREA:after,&.SORT:after,&.FILTER:after{ content:""; display:inline-block; width:5px; height:5px; margin-bottom:2px; margin-left:6px; border:2pxsolid#666; border-width:02px2px0; transform:rotate(45deg); -webkit-transform:rotate(45deg); -webkit-transition:.3s; transition:.3s; } &.current{ color:#0084ff; } &.current:after{ border-color:#0084ff; transform:rotate(225deg); -webkit-transform:rotate(225deg); }
chrome查看元素
全部区域tab被选中:
综合tab被选中
每次点击不同的tab时都会自动的渲染current这个css样式,这样就实现了下拉菜单的功能。
完整代码
/** *Class: *Author:miyaliunian *Date:2019/5/26 *Description:tabs选择器 *医院列表 */ importReact,{Component}from"react"; import{ZHPX,TABKAY}from"@api/Constant"; //Util import{fixedBody,looseBody}from"@utils/fixRollingPenetration"; //Redux import{connect}from"react-redux"; import{bindActionCreators}from"redux"; import{actionsastabActions,getTabs,getAreasList,getActionKey,getClosePanel}from"@reduxs/modules/tabs"; import{actionsashospitalActions,}from"@reduxs/modules/hospital"; //样式 import"./tabs.less"; classTabsextendsComponent{ /** *变化当前点击的item状态同时filter请求 *@paramfilterItem当前选中的元素 *@paramkey哪个tab是选中状态 */ changeDoFilter(filterItem,key,event){ const{tabActions:{changeFilter},hospitalActions:{filterHosiContentList}}=this.props; event.stopPropagation(); changeFilter(filterItem,key,(filter)=>{ filterHosiContentList(filter); }); } /** *筛选tab确定按钮 *@paramevent */ filterPanel(event){ const{tabActions:{closePanelAction},tabs,hospitalActions:{filterHosiContentList}}=this.props; event.stopPropagation(); closePanelAction(()=>{ filterHosiContentList(tabs) }) } /** *点击切换Tab *@paramkey */ onChangeTab(key){ const{actionKey,tabActions:{changeTab}}=this.props; letclosePanel=false; //如果前后点击的是同一个tab就关闭panel if(actionKey===key&&!this.props.closePanel){ closePanel=true; } closePanel?looseBody():fixedBody(); changeTab(key,closePanel); } /** *渲染顶部tab */ renderTabs(){ const{tabs,actionKey,closePanel}=this.props; //--------- if(!closePanel){ fixedBody(); }else{ looseBody(); } //--------- letaray=[]; for(letkeyintabs){ letitem=tabs[key]; letcls=item.key+"item"; if(item.key===actionKey&&!closePanel){ cls+="current"; } aray.push(this.onChangeTab(item.key)}> {item.text}