Created
September 17, 2014 04:18
-
-
Save andyyou/9a0a723facc3f1cd071b to your computer and use it in GitHub Desktop.
A Pen by AndyYou.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#example |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* @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') | |
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
.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