UNPKG

lm-tab

Version:

* 作者:winber * 邮箱:winberxie@163.com * 版本:**`0.4.0`**

266 lines (229 loc) 7.25 kB
/** * Created by winber<winberxie@163.com>. * ComponentName Tab * Desc 组件描述内容 * GroupName lm-component */ import React from 'react' import PropTypes from 'prop-types'; import classNames from 'classnames'; import './index.scss'; export const NavBar = (props) => { const {className, children, ...others} = props; const cls = classNames({ 'lm-nav-bar': true }, className); return ( <div className={cls} {...others}> {children} </div> ) } export const NavBarItem = (props) => { const {className, label, active, children, ...others} = props; const cls = classNames({ 'lm-nav-bar-item': true, 'lm-nav-bar-active': active }, className); return ( <div className={cls} {...others}> {label ? label : children} </div> ) } NavBarItem.propTypes = { active: PropTypes.bool, label: PropTypes.string, }; export const TabBar = (props) => { const {className, children, ...others} = props; const cls = classNames({ 'lm-tab-bar': true }, className); return ( <div className={cls} {...others}> {children} </div> ) } /** * TabBarItem 组件 * @param {object} props --属性对象 * @enum {string} desc 文本描述 * @enum {base64} activeIcon 选中时对应的icon * @enum {base64} icon 未选中时对应的icon * @enum {boolean} active 当前是否选中 true:选中 false:未选中 * @return {[React.Element]} 组件需要渲染的dom */ export const TabBarItem = (props) => { const {className, desc, active, activeIcon, icon, ...others} = props; const cls = classNames({ 'lm-tab-bar-item': true, 'lm-tab-bar-active': active }, className); return ( <div className={cls} {...others}> <img alt="" className='lm-tab-bar-icon' src={active ? activeIcon : icon}/> <p>{desc}</p> </div> ) } TabBarItem.propTypes = { active: PropTypes.bool, activeIcon: PropTypes.any.isRequired, icon: PropTypes.any.isRequired, desc: PropTypes.string.isRequired }; export const TabBody = (props) => { const {children, ...others} = props; return ( <div {...others}> {children} </div> ) } /** * TabBarItem 组件 * @param {object} props --属性对象 * @enum {boolean} active 当前是否选中 true:选中 false:未选中 * @return {[React.Element]} 组件需要渲染的dom */ export const TabBodyItem = (props) => { const {children, active, className, ...others} = props; const cls = classNames({ 'lm-tab-body-item': true, 'lm-tab-body-item-active': active }, className); return ( <div className={cls} {...others} > {children} </div> ) } export class Tab extends React.Component { constructor(props){ super(props); this.state = { /** * @description - 所选中的tabItem的索引 * @property {number} index 当前所选中的tabItem的索引 */ index: this.props.defaultIndex } }; static defaultProps = { type: 'normal', defaultIndex: 0, }; static propTypes = { type: PropTypes.string, onChange: PropTypes.func, defaultIndex: PropTypes.number }; /** * 点击tabItem的回调函数 * @param {number} index --当前所选中的tab索引 */ handleHeaderClick = (index) => { const prevIndex = this.state.index; this.setState({index},() => { this.props.onChange && prevIndex !== index && this.props.onChange(index); }); }; /** * 提取contentItem & navItem & 属性 * @param {React.Element} childrenInput --Tab 组件的childen * @return {object} --navbar的items & tabBody的items & navbar的props &tabBody的props */ parseChild(children) { //缓存navbar的items const ChildHeaders = []; //缓存tabBody的items const ChildContents = []; //缓存tabBody & bar的 props let tBodyProps, barProps; React.Children.map(children, child => { if (!child) return; const {children} = child.props; if (child.type === TabBarItem || child.type === NavBarItem){ ChildHeaders.push(child); if (children) ChildContents.push(<TabBodyItem children={children}/>); } if (child.type === TabBodyItem){ ChildContents.push(child); } if (child.type === NavBar || child.type === TabBar){ barProps = child.props; React.Children.map(child.props.children, item => { ChildHeaders.push(item); }) } if (child.type === TabBody){ tBodyProps = child.props; React.Children.map(child.props.children, item => { ChildContents.push(item); }) } }); return {ChildHeaders, ChildContents, tBodyProps, barProps}; }; /** * Tab需要render的内容 * @param {string} type --Tab组件的类型 * @param {React.Element} children -Tab组件的children * @param {object} props --Tab组件自定义的样式 * @return {React.Element} --Tab需要render的内容 */ renderBar(type, children, props) { const {ChildHeaders, ChildContents, tBodyProps, barProps} = this.parseChild(children); let _headers = ChildHeaders.map((item, idx)=>{ const { onClick, active, ...others }= item.props return React.cloneElement(item, { key: idx, active: this.state.index === idx, onClick: (e) => { onClick && onClick(e); this.handleHeaderClick(idx); }, ...others }); }); let _contents = ChildContents.map((item, idx)=>{ return React.cloneElement(item, { key: idx, active: this.state.index === idx }); }); if (type === 'tabBar'){ return ( <div {...props}> <TabBody {...tBodyProps}> {_contents} </TabBody> <TabBar {...barProps}> {_headers} </TabBar> </div> ); } if (type === 'navBar' || 'normal'){ return ( <div {...props}> <NavBar {...barProps}> {_headers} </NavBar> <TabBody {...tBodyProps}> {_contents} </TabBody> </div> ); } return false; } render() { const {children, type, defaultIndex, ...others} = this.props; return this.renderBar(type, children, others); } }