jimu-mobile
Version:
积木组件库助力移动端开发
143 lines (132 loc) • 3.93 kB
JavaScript
/**
* Created by yanshenshen on 17/11/2.
*/
import React from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';
import ReactDOM from 'react-dom';
class Tabs extends React.Component {
static propTypes = {
children: PropTypes.oneOfType([
PropTypes.arrayOf(PropTypes.node),
PropTypes.node,
]),
activeIndex: PropTypes.number, // 默认索引
isInLocal: PropTypes.bool, // 默认索引
onChange: PropTypes.func,
}
static defaultProps = {
activeIndex: 1,
isInLocal: false,
onChange() {},
}
constructor(props) {
super(props);
const { activeIndex, children } = this.props;
this.state = {
activeIndex: activeIndex > children.length ? children.length : activeIndex,
};
if (activeIndex > children.length) {
console.error('activeIndex值大于了元素个数');
}
this.handleTabClick = this.handleTabClick.bind(this);
}
componentDidMount() {
this.setTabHdX(this.state.activeIndex);
}
componentWillReceiveProps(nextProps) {
if (nextProps.activeIndex !== this.props.activeIndex) {
this.setState({
activeIndex: nextProps.activeIndex,
});
const { activeIndex, children } = nextProps,
newActiveIndex = activeIndex > children.length ? children.length : activeIndex;
this.state = {
activeIndex: newActiveIndex,
};
if (activeIndex > children.length) {
console.error('activeIndex值大于了元素个数');
}
this.setTabHdX(newActiveIndex);
}
}
// 设置当前选中导航位置
setTabHdX(activeIndex) {
const { tabsHd } = this,
NavNode = this[`tabsNav-${activeIndex}`],
TabsHdWidth = ReactDOM.findDOMNode(tabsHd).clientWidth,
NodeLeft = ReactDOM.findDOMNode(NavNode).offsetLeft,
NodeWidth = ReactDOM.findDOMNode(NavNode).clientWidth;
if ((NodeLeft + NodeWidth) > TabsHdWidth) {
ReactDOM.findDOMNode(tabsHd).scrollTo(NodeLeft, 0);
}
}
handleTabClick(activeIndex) {
if (activeIndex === this.state.activeIndex) {
return;
}
this.setState({ activeIndex });
this.props.onChange({ activeIndex });
}
renderTabNav() {
const { children } = this.props,
{ activeIndex } = this.state;
return (
<div className="jimu-tabs-hd" ref={(n) => { this.tabsHd = n; }}>
{React.Children.map(children, (child, i) => {
if (!child) { return; }
const navCls = classNames({
'jimu-tabs-nav': true,
'jimu-tabs-nav-active': i == (activeIndex - 1),
});
return (
<div
className={navCls}
key={i}
ref={n => this[`tabsNav-${i + 1}`] = n}
onClick={() => { this.handleTabClick(i + 1); }}
>
<b className="jimu-tabs-nav-bar">{child.props.tab}</b>
</div>
);
})}
</div>
);
}
renderTabContent() {
const { children } = this.props,
{ activeIndex } = this.state;
return (
<div className="jimu-tabs-bd">
{React.Children.map(children, (child, i) => {
if (!child) { return; }
const contentCls = classNames({
'jimu-tabs-content': true,
'jimu-tabs-content-active': i === (activeIndex - 1),
});
return (
<div className={contentCls} key={i}>
{child}
</div>
);
})}
</div>
);
}
render() {
const { className, isInLocal } = this.props;
const cls = classNames({
'jimu-tabs': true,
'jimu-tabs-in-local': isInLocal,
[className]: className,
});
return (
<div className={cls}>
{this.renderTabNav()}
{this.renderTabContent()}
</div>
);
}
}
export default Tabs;
// onClick={self.handleTabClick.bind(this, i + 1)}