【问题标题】:change scrollTop in reactjs在 reactjs 中更改 scrollTop
【发布时间】:2015-11-17 04:03:41
【问题描述】:

我刚学react,想实现一个功能: A,B都是组件,如果A滚动,那么B滚动

以下是我的代码

<A onScroll="handleScroll"></A>

//what i write now
handleScroll: function(event){
    var target = event.nativeEvent.target;

    //do something to change scrollTop value
    target.scrollTop += 1;

    // it looks the same as not use react
    document.getElementById(B).scrollTop = target.scrollTop;
}

但实际上我想要这样的代码

//what i want
<A scrollTop={this.props.scrollSeed}></A>
<B scrollTop={this.props.scrollSeed}></B>

//...
handleScroll(){
    this.setState({scrollSeed: ++this.state.scrollSeed})
}

类似于input

<input value="this.props.value"/>
<input value="this.props.value"/>
<input ref='c' onChange={handleChange}>

//...
handleChange: function() {
    // enter some code in c and then render in a and b automatically
}

换句话说,我想要一些属性,比如scrollTop(不同 表单&lt;input value={}&gt;,因为&lt;A scrollTop={}&gt;不起作用),绑定了一些状态,所以我可以使用setState,它们会自己更新。

我之前用谷歌搜索过,但找不到答案。希望我蹩脚的英语不会让你感到困惑。

【问题讨论】:

    标签: javascript reactjs


    【解决方案1】:

    有许多模式可以实现这一点。这个sample 是我想出的让你振作起来的方法。

    首先创建一个组件类,其中包含一个用于滚动效果的超大元素。当拖动滚动条时,该组件调用其handleScrollReact 属性通知其父组件,其值为scrollTop

    var Elem = React.createClass({
        render() {
            return (
                <div ref="elem"
                    onScroll={ this.onScroll }
                    style={{ width: "100px", height: "100px", overflow: "scroll" }}>
                    <div style={{ width: "100%", height: "200%" }}>Hello!</div>
                </div>
            );
        },
        componentDidUpdate() {
            this.refs.elem.scrollTop = this.props.scrollTop;
        },
        onScroll() {
            this.props.handleScroll( this.refs.elem.scrollTop );
        }
    });
    

    父组件,即包装器,将滚动顶部值保持在其状态。它的handleScroll 作为回调传递给子组件。子元素上的任何滚动都会触发回调、设置状态、导致重绘并更新子组件。

    var Wrapper = React.createClass({
        getInitialState() {
            return {
                scrollTop: 0
            }
        },
        render() {
            return (
                <div>
                    <Elem scrollTop={ this.state.scrollTop } handleScroll={ this.handleScroll } />
                    <Elem scrollTop={ this.state.scrollTop } handleScroll={ this.handleScroll } />
                </div>
            );
        },
        handleScroll( scrollTop ) {
            this.setState({ scrollTop });
        }
    });
    

    并呈现包装器,假设现有&lt;div id="container"&gt;&lt;/div&gt;

    ReactDOM.render(
        <Wrapper />,
        document.getElementById('container')
    );
    

    【讨论】:

    • 感谢您的帮助!而且我发现不用ReactDOM.findDOMNode( )this.refs.elem就够用了(还能节省10%的CPU使用率,^_^);在此之前,我只是尝试将我的代码放在componentWillMount,但它应该是componentDidUpdate;毕竟,再次感谢;
    • @edeity,这是真的;修订。
    【解决方案2】:

    2019年的答案

    首先,修复:

    const resetScrollEffect = ({ element }) => {
      element.current.getScrollableNode().children[0].scrollTop = 0
    }
    
    const Table = props => {
      const tableRef = useRef(null)
      useEffect(() => resetScrollEffect({ element: tableRef }), [])
      return (
        <Component>
          <FlatList
            ref={someRef}
          />
        </Component>
      )
    }
    

    二、一点解释:

    我知道你来这里的原因是什么,但我在我的 FlatList 中使用了flex-direction: column-reverse(它是一个元素列表)。我需要这个属性来达到z-index 的目的。但是,浏览器会将此类元素(表格、聊天等)的滚动位置设置到末尾 - 这可能很有用,但在我的情况下不需要。

    此外,示例使用React Hooks 显示,但您可以使用older更传统的方式来定义 refs

    【讨论】:

    • 我认为这是关于 React Web 的,您的回答适用于 React Native。我也想知道如何触发点击效果。加载时以及任何状态或道具更改时似乎都会调用效果。
    • 也许将 resetScrollEffect 重命名为 resetScroll 并让按钮显示为 onClick={ .resetScroll({ element: tableRef }) }
    • @BenjaminAtkin 将函数命名为 *Effect 是一个标准,当它用于反应中的 useEffect 时。但是与问题相对应的主线是element.current.getScrollableNode().children[0].scrollTop =,因为上面答案中的element.current.scrollTop = 对我不起作用(它在一些旧时代起作用)
    • 谢谢,必须登录并投票!很难找到钩子的解决方案。 element.current.scrollTop 完美运行。
    【解决方案3】:

    this.refs 已弃用。使用 reactjs.org/docs/refs-and-the-dom.html#creating-refs

    import React from 'react';
    
    class SomeComponent extends React.Component {
      constructor(props) {
        super(props);
        this.resultsDiv = React.createRef();
      }
    
      someFunction(){
         this.resultsDiv.current.scrollIntoView({behavior: 'smooth'});
    
         // alternative:
         // this.resultsDiv.current.scrollTop = 0;
      }
    
      render() {
        return (
          <div ref={this.resultsDiv} />
        );
      }
    }
    
    export default SomeComponent;
    
    
    

    【讨论】:

    • @jimish 试试this.resultsDiv.current.scrollIntoView({behavior: 'smooth'});。由于与 css 布局、div 定位相关的其他问题,这可能不起作用。尝试在您知道使用默认 css 定位的其他元素上使用它。
    【解决方案4】:

    这是Season's answer 的更新版本,包括一个可运行的sn-p。它使用creating refs 的推荐方法。

    class Editor extends React.Component {
        constructor(props) {
            super(props);
            this.content = React.createRef();
            this.handleScroll = this.handleScroll.bind(this);
        }
    
        componentDidUpdate() {
            this.content.current.scrollTop = this.props.scrollTop;
        }
        
        handleScroll() {
            this.props.onScroll( this.content.current.scrollTop );
        }
    
        render() {
            let text = 'a\n\nb\n\nc\n\nd\n\ne\n\nf\n\ng';
            return <textarea
                ref={this.content}
                value={text}
                rows="10"
                cols="30"
                onScroll={this.handleScroll}/>;
        }
    }
    
    class App extends React.Component {
        constructor(props) {
            super(props);
            this.state = {scrollTop: 0};
            this.handleScroll = this.handleScroll.bind(this);
        }
    
        handleScroll(scrollTop) {
            this.setState({scrollTop: scrollTop});
        }
    
        render() {
            return <table><tbody>
                <tr><th>Foo</th><th>Bar</th></tr>
                <tr>
                    <td><Editor
                        scrollTop={this.state.scrollTop}
                        onScroll={this.handleScroll}/></td>
                    <td><Editor
                        scrollTop={this.state.scrollTop}
                        onScroll={this.handleScroll}/></td>
                </tr>
            </tbody></table>;
        }
    }
    
    ReactDOM.render(
        <App/>,
        document.getElementById('root')
    );
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
    <div id="root"></div>

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-12-14
      • 2020-12-13
      • 1970-01-01
      • 1970-01-01
      • 2017-05-26
      • 1970-01-01
      • 2023-03-07
      相关资源
      最近更新 更多