2017-06-16 70 views
0

我正在开发一个聊天平台进行多个聊天,他可以在聊天之间切换。如何使用react/redux设计多标签聊天?

var MessageList = React.createClass({ 
    render() { 
     return (
      <div className='messages'> 
      <h2> Conversation: </h2> 
      { 
       this.props.messages.map((message, i) => { 
        return (
         <Message 
          key={i} 
          user={message.user} 
          text={message.text} 
         /> 
       ); 
       }) 
      } 
     </div> 
     ); 
}}) 

我们拿邮件列表的一个例子,当用户切换聊天标签,这将发生改变。重新渲染与新的messageList相同的组件对于聊天是有意义的,但是当有100个这样的组件更改时,如果有聊天切换时,那么将会有很多重新绘制/渲染(我知道只有diff会是改变了但仍然)

我想为不同的聊天创建不同的元素,并根据活动聊天隐藏和显示它们。但是,反应是在一个单独的dom下进行的,并将dom替换为已经返回的地方。

React.render(<ChatApp/>, document.getElementById('app')); 

任何人都可以帮我设计这里?

在此先感谢。

+0

看看这个。 http://www.jeasyui.com/tutorial/layout/tabs2_demo.html# https://github.com/reactabular/reactabular/issues/90 –

回答

0

var Tabs = React.createClass({ 
 
\t displayName: 'Tabs', 
 
\t propTypes: { 
 
    selected: React.PropTypes.number, 
 
    children: React.PropTypes.oneOfType([ 
 
     React.PropTypes.array, 
 
     React.PropTypes.element 
 
    ]).isRequired 
 
    }, 
 
    getDefaultProps: function() { 
 
    \t return { 
 
    \t selected: 0 
 
    }; 
 
    }, 
 
    getInitialState: function() { 
 
    return { 
 
    \t selected: this.props.selected 
 
    }; 
 
    }, 
 
    shouldComponentUpdate(nextProps, nextState) { 
 
    \t return this.props !== nextProps || this.state !== nextState; 
 
    }, 
 
    handleClick: function (index, event) { 
 
    \t event.preventDefault(); 
 
    this.setState({ 
 
    \t selected: index 
 
    }); 
 
    }, 
 
    _renderTitles: function() { 
 
    \t function labels(child, index) { 
 
    \t var activeClass = (this.state.selected === index ? 'active' : ''); 
 
    \t return (
 
     \t <li key={index}> 
 
     \t <a href="#" 
 
      \t className={activeClass} 
 
      \t onClick={this.handleClick.bind(this, index)}> 
 
      \t {child.props.label} 
 
      </a> 
 
     </li> 
 
    ); 
 
    } 
 
    \t return (
 
    \t <ul className="tabs__labels"> 
 
     \t {this.props.children.map(labels.bind(this))} 
 
     </ul> 
 
    ); 
 
    }, 
 
    _renderContent: function() { 
 
    \t return (
 
    \t <div className="tabs__content"> 
 
\t  \t {this.props.children[this.state.selected]} 
 
     </div> 
 
    ); 
 
    }, 
 
\t render: function() { 
 
    \t return (
 
    \t <div className="tabs"> 
 
     {this._renderTitles()} 
 
     \t {this._renderContent()} 
 
     </div> 
 
    ); 
 
    } 
 
}); 
 

 
var Pane = React.createClass({ 
 
\t displayName: 'Pane', 
 
    propTypes: { 
 
    label: React.PropTypes.string.isRequired, 
 
    children: React.PropTypes.element.isRequired 
 
    }, 
 
\t render: function() { 
 
    \t return (
 
    \t <div> 
 
     \t {this.props.children} 
 
     </div> 
 
    ); 
 
    } 
 
}); 
 

 
var App = React.createClass({ 
 
\t render: function() { 
 
    \t return (
 
    \t <div> 
 
     <Tabs selected={0}> 
 
      <Pane label="Tab 1"> 
 
      <div>This is my tab 1 contents!</div> 
 
      </Pane> 
 
      <Pane label="Tab 2"> 
 
      <div>This is my tab 2 contents!</div> 
 
      </Pane> 
 
      <Pane label="Tab 3"> 
 
      <div>This is my tab 3 contents!</div> 
 
      </Pane> 
 
     </Tabs> 
 
     </div> 
 
    ); 
 
    } 
 
}); 
 
    
 
ReactDOM.render(<App />, document.querySelector('.container'));
* { 
 
    box-sizing: border-box; 
 
    -webkit-box-sizing: border-box; 
 
    -moz-box-sizing: border-box; 
 
} 
 
body { 
 
    font: 300 14px/1.4 'Helvetica Neue', Helvetica, Arial, sans-serif; 
 
    background: #eee; 
 
    margin: 0; 
 
    padding: 0; 
 
} 
 
.tabs { 
 
    margin: 25px; 
 
    background: #fff; 
 
    border: 1px solid #e5e5e5; 
 
    border-radius: 3px; 
 
} 
 
.tabs__labels { 
 
    margin: 0; 
 
    padding: 0; 
 
} 
 
.tabs__labels li { 
 
    display: inline-block; 
 
} 
 
.tabs__labels li a { 
 
    padding: 8px 12px; 
 
    display: block; 
 
    color: #444; 
 
    text-decoration: none; 
 
    border-bottom: 2px solid #f5f5f5; 
 
} 
 
.tabs__labels li a.active { 
 
    border-bottom-color: #337ab7; 
 
} 
 
.tabs__content { 
 
    padding: 25px; 
 
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script> 
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script> 
 

 
<div class="container"></div>

+0

感谢您的详细解释。 @Praveen 但在这种情况下,你会知道锄头有很多标签,但在我的情况下,它是动态的。我创建了一个动态的,并将它连接到与其他dom平行的dom下,甚至没有触及/渲染其他标签!我如何通过反应来实现这一点。 – iamshravan

+0

你可以很容易地使动态做这样的事情: 常量窗格=({} anArrayOfIndividualPaneObjects)=>(

{anArrayOfIndividualPaneObjects.map(pane => ( \t
pane.contents
))}
); 并传递App组件中的窗格数组。您还可以通过向App组件中的此数组添加新对象的方法来动态添加新选项卡 –

0

你的意思是终极版,所以我会尽量给一些见解,但懒得提供任何代码,因为这将是太大/复杂。

事先,如果需要,在处理嵌套JSON格式时可以使用normalizr,因为REDX爱是不可变的,嵌套使它更难变成不可变的。

减速机:

chats { userid:"", message:"", time:"" }, 
users { userid:"", name:"" }, 
app { selectedUserId:"" } 

现在,要呈现的标签数量/显示的是等于用户数量。所选标签基于app.selectedUserId。在面板中呈现的消息将是聊天,其中userid等于app.selectedUserId。一些片段:

var lo = require('lodash'); 
var selectedChats = lo.filter(this.props.chats, k => k.userid == app.selectedUserId); 

var messagesDom = selectedChats.map(k => <MessageLine chat={k}); 
var chatTabsDom = this.props.users.map(k => <ChatTab userid={k.userid} className={ k.userid == app.selectedUserId ? "active" : "" }>); 

return <div> 
    <Tabs>{chatTabsDom}</Tabs> 
    <Messages>{messagesDom}</Messages> 
</div>;