Skip to content

Instantly share code, notes, and snippets.

@andyyou
Created September 17, 2014 04:18
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save andyyou/9a0a723facc3f1cd071b to your computer and use it in GitHub Desktop.
Save andyyou/9a0a723facc3f1cd071b to your computer and use it in GitHub Desktop.
A Pen by AndyYou.
/**
* @jsx React.DOM
*/
/**
* 判斷是否為 LI Tab 節點
*/
function isTabNode (node) {
return node.nodeName === 'LI' &&
node.getAttribute('role') === 'tab';
}
/**
* 簡易的替 tab 取一個唯一的 ID
*/
var uuid = (function() {
var count = 0;
return function () {
return 'react-tab-' + count++;
}
})();
/**
* 由上而下的開發流程,先定義 App 的結構。
*/
var App = React.createClass({
render: function () {
return (
<div className='container'>
<Tabs selectedIndex={0}>
<TabList>
<Tab>Iron man</Tab>
<Tab>Superman</Tab>
<Tab>Lucy</Tab>
</TabList>
<TabPanel>
鋼鐵人系列電影
</TabPanel>
<TabPanel>
超人再起
</TabPanel>
<TabPanel>
露西 100 %
</TabPanel>
</Tabs>
</div>
);
}
});
/**
* Tabs
*/
var Tabs = React.createClass({
propTypes: {
selectedIndex: React.PropTypes.number
},
getDefaultProps: function () {
return {
selectedIndex: 0
}
},
getInitialState: function () {
return {
selectedIndex: this.props.selectedIndex
}
},
handleSelected: function (index) {
if (index === this.state.selectedIndex) return;
if (index < 0) return;
this.setState({selectedIndex: index});
},
handleClick: function (e) {
var node = e.target;
if (isTabNode(node)) {
var index = [].slice.call(node.parentNode.children).indexOf(node);
this.handleSelected(index);
}
},
render: function () {
var count = 0, index = 0;
var state = this.state;
var children = React.Children.map(this.props.children, function (child) {
var component = null;
if (count++ === 0) {
component = React.addons.cloneWithProps(child, {
ref: 'tablist',
children: React.Children.map(child.props.children, function (tab) {
var ref = 'tab-' + index,
selected = state.selectedIndex === index;
index++;
return React.addons.cloneWithProps(tab, {
ref: ref,
selected: selected
});
})
});
index = 0;
} else {
var ref = 'panel-' + index,
selected = state.selectedIndex === index;
index++;
component = React.addons.cloneWithProps(child, {
ref: ref,
selected: selected
});
}
return component;
});
return (
<div className='react-tabs'
onClick={this.handleClick}>
{children}
</div>
)
}
});
/**
* Tab 選單列的標簽
*/
var Tab = React.createClass({
getInitialState: function () {
return {
selected: false
}
},
componentDidMount: function () {
if (this.props.selected) {
this.getDOMNode().setAttribute('selected', 'selected');
} else {
this.getDOMNode().removeAttribute('selected');
}
},
componentDidUpdate: function () {
if (this.props.selected) {
this.getDOMNode().setAttribute('selected', 'selected');
} else {
this.getDOMNode().removeAttribute('selected');
}
},
render: function () {
var cx = React.addons.classSet;
var classes = cx({
'react-tab': true,
'active': this.props.selected
});
return (
<li className={classes} role='tab'>
{this.props.children}
</li>
)
}
});
/**
* TabList: Tab 標簽的容器
*/
var TabList = React.createClass({
render: function () {
return (
<ul className='react-tab-list' role='tablist'>
{this.props.children}
</ul>
);
}
});
/**
* TabPanel 對應內容
*/
var TabPanel = React.createClass({
getDefaultProps: function () {
return {
selected: false
}
},
render: function () {
var cx = React.addons.classSet;
var classes = cx({
'react-tab-panel': true,
'active': this.props.selected
});
return (
<div className={classes} role='tabpanel'>
{this.props.children}
</div>
)
}
})
React.renderComponent(
<App />,
document.getElementById('example')
)
.react-tabs {
.react-tab-list {
list-style: none;
margin: 0;
background: #1C5A74;
.react-tab {
display: inline-block;
line-height: 3em;
padding-left: 1em;
padding-right: 1em;
color: #D7A396;
&.active {
background: #55BEC1;
color: #1C5A74;
}
}
}
.react-tab-panel {
display: none;
&.active {
display: block;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment