ReactJS-将溢出的元素放入一个“"下拉按钮
ReactJS - put overflown elements into a "..." dropdown button
我的页面顶部有以下UI元素:
|[Static1] [Dynamic1] [Dynamic2] [Dynamic3] [Static2]|
所以Static1
是一些向左粘贴的徽标组件,Static2
是一些向右粘贴的用户菜单组件。
现在,我有一个集合组件,它显示从DB加载的几个动态元素。
如果没有太多这样的组件,一切都很好,但如果有更多,我不想有任何换行符,只想有一些"更多"菜单,比如:
|[Static1] [Dynamic1] [Dynamic2] [Dynamic3] [Dynamic4][...][Static2]|
当我点击CCD_ 3按钮时,我不会看到动态组件的垂直列表。
动态项目列表存储在ElementList
组件中,代码如下:
React.createClass({
render() {
return (
<div ref="listparent">
{ this.props.elements.map((element) => {
return <Element
ref={"element-"+element.name}
key={element.name}
})}
</div>
)
}
});
this.props.elements
是作为道具传递的集合。我尝试了所有这些行的东西,但要么不起作用,要么在每次刷新页面时都不起作用:
export default React.createClass({
getInitialState(){
return {
visibleElements: this.props.elements,
hiddenElements: []
}
},
componentDidMount() {
this.rearrange();
},
componentDidUpdate(){
this.rearrange();
},
rearrange(){
var element = ReactDOM.findDOMNode(this.refs.listparent);
let visibleElements = [];
let hiddenElements = [];
for(var i=0; i< this.props.elements.length; i++)
{
var currentElement = this.props.elements[i];
var domElement = ReactDOM.findDOMNode(this.refs["element-"+element.name]);
if(domElement) {
if (domElement.offsetTop + domElement.offsetHeight >
element.offsetTop + element.offsetHeight ||
domElement.offsetLeft + domElement.offsetWidth >
element.offsetLeft + element.offsetWidth - 200) {
hiddenElements.push(currentElement);
}
else {
visibleElements.push(currentElement);
}
}
}
if(this.state.visibleElements.length != visibleElements.length) {
this.setState({
visibleElements: visibleElements,
hiddenElements: hiddenElements
})
}
},
render() {
return (
<div ref="listparent">
{ this.state.visibleElements.map((element) => {
return <Element
ref={"element-"+element.name}
key={element.name} />
})}
{ this.state.hiddenElements.length >0 &&
<DropdownMenu
Header="..."
>
{ this.state.hiddenElements.map((element) => {
return <Element
ref={"element-"+element.name}
key={element.name} />
})}
</DropdownMenu>
}
</div>
)
}
});
以下是我想做的一个粗略的jsFiddle:https://jsfiddle.net/3uf9r8ne/
我不知道这是否是最好的解决方案,也不知道它有多健壮,但至少目前对我来说是有效的。
Js报价:https://jsfiddle.net/1w6m1n6h/
var Dropdown = React.createClass({
getInitialState(){
return {
isOpen: false
}
},
componentWillMount() {
document.addEventListener('click', this.handleClick, false);
},
componentWillUnmount() {
document.removeEventListener('click', this.handleClick, false);
},
handleClick: function (e) {
var component = ReactDOM.findDOMNode(this.refs.component);
if (e.target == component || $(component).has(e.target).length) {
// Inside the component
}
else{
// Outide
this.setState({ isOpen: false});
}
},
render()
{
return (
<div ref="component" className="dropdown">
<div className="dropdown-button" onClick={() => this.setState({ isOpen : !this.state.isOpen})}>{this.props.Header}</div>
{
this.state.isOpen && (
<div className="dropdown-menu" onClick={() => this.setState({ isOpen : false})}>
{React.Children.map(this.props.children, (item) => item)}
</div>
)
}
</div>
);
}
});
var Card = React.createClass({
render() {
let className = "card";
if(this.props.isHidden)
className += " is-hidden";
return (
<div className={className}>{this.props.name}</div>
)
}
});
var Cards = React.createClass({
getInitialState() {
return {
vCards: [],
hCards: [],
lastSetCards: [],
preMounted: false,
laidOut: false
};
},
rearrange() {
_.throttle(this.setState({laidOut: false, preMounted: false}), 100);
},
componentDidMount() {
window.addEventListener('resize', this.rearrange);
},
componentWillUnmount() {
window.removeEventListener('resize', this.rearrange);
},
componentDidUpdate() {
if(this.props.cards.length != this.state.lastSetCards || !this.state.preMounted) {
this.setState({
lastSetCards: this.props.cards.length,
vCards: this.props.cards,
preMounted: true,
laidOut: false
});
}
if(this.state.preMounted && !this.state.laidOut) {
var element = ReactDOM.findDOMNode(this.refs.listparent);
let visibleCards = [];
let hiddenCards = [];
for(var i=0; i< this.props.cards.length; i++)
{
var card = this.props.cards[i];
var cardElement = ReactDOM.findDOMNode(this.refs["card-"+card]);
if(cardElement) {
if (cardElement.offsetTop + cardElement.offsetHeight >
element.offsetTop + element.offsetHeight ||
cardElement.offsetLeft + cardElement.offsetWidth >
element.offsetLeft + element.offsetWidth - 160) {
hiddenCards.push(card);
}
else {
visibleCards.push(card);
}
}
}
this.setState({
vCards: visibleCards,
hCards: hiddenCards,
laidOut: true
});
}
},
render() {
return (<div className="cards-top" ref="listparent">
<div className="cards" >
{this.state.vCards.map((c)=> <Card ref={"card-"+c} key={c} name={c} />)}
</div>
<Dropdown Header="MORE">
{this.state.hCards.map((c)=> <Card isHidden={true} key={c} name={c} />)}
</Dropdown>
</div>
)
}
});
var Hello = React.createClass({
getInitialState() {
return {
cards: ["one", "two" ]
};
},
componentDidMount() {
this.setState({
cards: ["one", "two", "three", "four", "five", "six", "seven", "eight",
"nine", "ten", "eleven", "twelve", "thirteen", "fourteen"]
});
},
render: function() {
let addNew = () => {
this.state.cards.push("additional_"+this.state.cards.length);
this.setState({
cards: this.state.cards
})
};
return (
<div>
<div className="header">
<div className="logo">Logo</div>
<div className="user">User</div>
<Cards cards={this.state.cards} />
<div className="clear"></div>
</div>
<br/><br/>
<button onClick={addNew}>Add</button>
</div>);
}
});
ReactDOM.render(
<Hello name="World" />,
document.getElementById('container')
);
.logo
{
float: left;
margin: 5px;
padding: 5px;
border: solid 1px blue;
}
.user
{
float: right;
margin: 5px;
padding: 5px;
border: solid 1px blue;
}
.header{
position: relative;
max-height: 10px;
height: 10px;
width: 100%;
}
.cards
{
position: relative;
display: inline-block;
vertical-align: top;
white-space: nowrap;
}
.clear
{
clear: both;
}
.card
{
display: inline-block;
margin: 5px;
padding: 5px;
border: solid 1px blue;
}
.cards-top
{
display: block;
white-space: nowrap;
vertical-align: top;
width: 100%;
border: green 1px solid;
}
.dropdown
{
display: inline-block;
}
.is-hidden
{
display: block;
}
.dropdown-button
{
margin: 5px;
padding: 5px;
border: solid 1px blue;
}
<script src="https://facebook.github.io/react/js/jsfiddle-integration-babel.js"></script>
<div id="container">
<!-- This element's contents will be replaced with your component. -->
</div>
相关文章:
- 尝试使用Javascript正则表达式来获取“&"分隔文本,无论它是否's是最后一个值
- jQuery"焦点”;在一个实例中有效,但在其他实例中无效
- 我如何选择/点击一个带有for=“”的元素"属性[量角器]
- 我收到一个类型错误,其中包含-"$不是函数“;使用noConflict时
- 我正在使用php includes来构建一个多页面网站.使用jquery,我将如何添加一个类"活动的”;添加到
- 获取"下一个“;对象中的数值
- 我怎样才能使一个类型=“;提交”;在css中看起来像一个type="按钮”;
- 为什么下面抛出一个“;对象没有't支持属性或方法'importNode'"在IE11中
- JQuery:如何强制选择一个选项为"选择“;,使用FancySelect插件
- 我想制作一个代码;a“;变成“;b”"b”;变成“;c”;,等等
- 你如何做一个sql"像“;在javascript中使用azuremobilesdk进行查询
- 说明Node.js项目:是否只有一个"服务器文件“;在node.js中
- 主路由器在路由“”的末尾附加一个#"导致dom中引用锚点在Backbone/Require应用程序中不起作用
- ReactJS-将溢出的元素放入一个“"下拉按钮
- 如何添加另一个"条目“;转换为此JSON
- 错误:未捕获的异常:[exception.."字符串包含一个..quot;
- 如何隐藏所有下一个"字段集“;元素使用jQuery
- 为什么smooth scrolling.js抛出了一个"$target.offset(..)未定义”;错误
- 匹配一个“"在特定图案之后,同时排除该图案.(JavaScript中的lookbacking)
- 我如何将这个javascript/jQuery转换为一个"不内联”;作用