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}