速度反应 - 组件更新后动画scrollTop

时间:2016-02-23 00:02:18

标签: javascript animation reactjs velocity.js

我正在编写一个简单的“控制台”,以聊天方式显示消息。消息从底部出现,然后向上移动。

我有工作代码,但是每次添加新的“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。

1 个答案:

答案 0 :(得分:4)

velocity-react插件提供已实现的React组件,用于使用Velocity的动画。

我想滚动功能也可以通过动画实现,但Velocity库有scroll command。我已经启动了速度反应插件,它为动画提供了界面(组件)。没有任何对Velocity命令的支持。

在React中使用Velocity命令非常简单。 我根据您的问题创建了react-velocity-scroll repo,并且有一个以聊天方式发送/列出邮件的现场演示。

请注意,Velocity库通过velocity-react插件包含在示例中。它建议包含用于未来高级动画的插件,因为它提供了已经实现的React组件来使用Velocity的动画。然而,回购不使用任何动画。它仅使用Velocity库的scroll命令。如果您愿意 - 您可以单独导入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;