2017-06-16 66 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>;