ReactJS - 将溢出元素放入“...”下拉按钮

时间:2015-12-13 16:40:41

标签: javascript html dom reactjs

我的页面顶部有以下UI元素:

|[Static1] [Dynamic1] [Dynamic2] [Dynamic3]                [Static2]|

所以Static1是一些贴在左侧的徽标组件,Static2是一些贴在右侧的用户菜单组件。

现在我有一个集合组件,它显示从DB加载的几个动态元素。

一切都很好,如果没有太多的这些组件,但如果有更多,我不会有任何换行,只有一些堡垒的“更多”菜单,如:

|[Static1] [Dynamic1] [Dynamic2] [Dynamic3] [Dynamic4][...][Static2]|

当我点击[...]按钮时,我不是动态组件的垂直列表。

动态项列表存储在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/

1 个答案:

答案 0 :(得分:0)

让它工作,我不知道这是最好的解决方案,还是它有多强大,但至少目前适用于我。

JsFiddle:https://jsfiddle.net/1w6m1n6h/

class Package {
    public function method($fooArg = 1, $barArg = 1)
    {
        list $fizzArg, $fooBarArg = $this->someLogic($fooArg, $barArg);

        return new SomeClass(
            $fizzArg,
            $buzzArg
        );    
    }

    public function newMethod($fooArg = 1, $barArg = 1)
    {
        list $fizzArg, $fooBarArg = $this->someLogic($fooArg, $barArg);

        return new MyNewClass(
            $fizzArg,
            $fooBarArg
        );
    }

    protected function someLogic($fooArg, $barArg)
    {
        // some logic

        return [
            $fizzArg,
            $fooBarArg
        ]
    }
}
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;
}