2016-02-23 35 views
9

我正在寫一個簡單的「控制檯」,以類似聊天的方式顯示消息。隨着消息從底部出現,並向上移動。組件更新後的速度反應 - 動畫scrollTop

我有工作代碼,但我希望通過將容器滾動到底部每次添加新的「li」時將出現的消息動畫化。

當前代碼:

import React from 'react'; 
import { render, findDOMNode } from 'react-dom'; 


export default React.createClass({ 
    componentDidUpdate : function(){ 
     var node = findDOMNode(this); 
     node.scrollTop = node.scrollHeight; 
    }, 
    render() { 
     return (
      <ul id="log"> 
      { 
       this.props.messages.map(function(message, index){ 
        return <li key={index}>[{message.time.format('HH:mm:ss')}] {message.action}</li> 
       }) 
      } 
      </ul> 
     ) 
    } 
}) 

messages丙來自父組件和存儲。

我發現這個速度插件:https://github.com/twitter-fabric/velocity-react,我無法弄清楚如何在我的情況下使用它。所有的例子似乎都不適用(或者我可能只是不理解它們)。

我很新的反應,有些概念仍然困惑我,所以請理解。

我不想使用jQuery。

+0

所以你長了的反應部分工作和u [R尋求PUR e js滾動嗎? – goldylucks

+0

是的,上面的代碼正在工作。我想爲動畫滾動。我知道如何使用jQuery來做到這一點,但附加jQuery的反應感覺很愚蠢。與此同時,React動畫插件讓我無法理解。我之前使用過「純」速度,並且我知道它的性能如何。能夠在React中使用它會很好。所以這個問題實際上是關於速度js,但我願意接受其他建議。 –

+0

更準確的標題將b:「沒有jquery的javascript滾動動畫」;這將hav帶來你在這裏:http://stackoverflow.com/questions/8917921/cross-browser-javascript-not-jquery-scroll-to-top-animation – goldylucks

回答

3

velocity-react插件爲使用Velocity的動畫提供了已經實現的React組件。

我想滾動功能也可以通過動畫來實現,但Velocity庫有scroll command。我已經展示了velocity-react插件,它爲動畫提供了接口(組件)。 Velocity命令沒有任何支持。

在React中使用Velocity命令非常簡單。 我已根據您的問題創建react-velocity-scroll回購,並且有一個以類似聊天的方式發送/列出消息的現場演示。

請注意,速度庫包含在通過velocity-react插件的示例中。它建議將該插件包含在未來的高級動畫中,因爲它提供了已經實現的使用Velocity動畫的React組件。但回購不使用任何動畫。它只使用Velocity庫的滾動命令。如果你願意 - 你可以單獨導入Velocity庫。

但是,這裏是我的組件。請關注MessageItem組件 - 一旦添加了新消息,然後向下滾動到該組件。

應用

import React from 'react'; 
import MessagesList from './MessagesList'; 

const style = { 
    textAlign: 'center' 
}; 

class App extends React.Component{ 
    constructor(props) { 
     super(props); 

     this.state = { 
      /** 
      * @type Array - Store sent messages 
      */ 
      messages: [], 
      /** 
      * @type String - Store the input value. 
      * It's reset on message sent 
      */ 
      text: '' 
     } 
    } 

    handleOnChange(e) { 
     const text = e.target.value; 
     this.setState({ text }); 
    } 

    handleOnKeyPress(e) { 
     const text = e.target.value; 

     // Send the message on `Enter` button press 
     if (e.key === 'Enter') { 
      this.sendMessage(text); 
     } 
    } 

    /** 
    * Add the message to the state and reset the value 
    * of the input 
    * 
    * @param String text - Message text 
    */ 
    sendMessage(text) { 
     const { messages } = this.state; 
     const message = { date: new Date(), text }; 

     this.setState({ 
      messages: messages.concat([message]), 
      text: '' 
     }); 
    } 

    render() { 
     const { messages, text } = this.state; 

     return <div style={style}> 
      <h1>Please enter your text message:</h1> 

      <input 
       value={text} 
       placeholder="Press Enter for sending" 
       onChange={this.handleOnChange.bind(this)} 
       onKeyPress={this.handleOnKeyPress.bind(this)} /> 

      <MessagesList messages={messages} /> 
     </div> 
    } 
} 

export default App; 

MessagesList

import React from 'react'; 
import MessageItem from './MessageItem'; 

const style = { 
    height: '100px', 
    overflowY: 'scroll' 
}; 

const MessagesList = (props) => { 
    let { messages } = props; 

    messages = messages.map(function(message, index){ 
     return <MessageItem key={index} index={index} message={message} /> 
    }); 

    return <ul style={style}>{messages}</ul> 
}; 

export default MessagesList; 

MessageItem

import React from 'react'; 
import ReactDOM from 'react-dom'; 
const Velocity = require('../node_modules/velocity-react/lib/velocity-animate-shim'); 

const style = { 
    listStyle: 'none' 
}; 

class MessageItem extends React.Component{ 
    componentDidMount() { 
     const parentNode = ReactDOM.findDOMNode(this).parentNode; 
     const node = ReactDOM.findDOMNode(this); 

     // Once a new item is being added, then scroll down to it 
     Velocity(node, 'scroll', { 
      duration: 500, 
      container: parentNode, 
      queue: false 
     }); 
    } 

    render() { 
     const { message } = this.props; 

     return <li style={style}>{message.date + ' - ' + message.text}</li> 
    } 
} 

export default MessageItem;