如何使用 React js 添加平滑滚动返回顶部按钮?

Posted

技术标签:

【中文标题】如何使用 React js 添加平滑滚动返回顶部按钮?【英文标题】:How to Add Smooth Scrolling Back To Top Button using react js? 【发布时间】:2016-03-17 15:44:07 【问题描述】:

我已经使用 jquery 实现了这个,但想创建一个组件来响应做同样的事情

<script>            
jQuery(document).ready(function() 
    var offset = 220;
    var duration = 500;
    jQuery(window).scroll(function() 
        if (jQuery(this).scrollTop() > offset) 
            jQuery('.move-top').fadeIn(duration);
         else 
            jQuery('.move-top').fadeOut(duration);
        
    );

    jQuery('.move-top').click(function(event) 
        event.preventDefault();
        jQuery('html, body').animate(scrollTop: 0, duration);
        return false;
    )
);
</script>

在我的页脚中

<a href="#" class="move-top">↑</a>

【问题讨论】:

如果这是你个人学习react,那么这是一个很好的小代码学习。但如果这应该用于实际产品,为什么要引入 react 来做这么简单的事情? 仅供学习。我想以反应的方式来做。 【参考方案1】:

首先,我们需要跟踪页面在组件状态下的滚动情况。这种跟踪应该只在组件安装时发生。可以这样做:

getInitialState: function() 
  return  scrollTop: 0 ;
,
componentWillMount: function() 
  window.addEventListener('scroll', this.handleScroll);
,
componentWillUnmount: function() 
  window.removeEventListener('scroll', this.handleScroll);
,
handleScroll: function() 
   this.setState(scrollTop: $(window).scrollTop());
,

注意:这仍然是使用 jQuery 来获取当前滚动位置。请参阅 this question 以在不使用 jQuery 的情况下执行此操作。

然后我们需要渲染组件:

scrollToTop: function() 
  $(window).animate(scrollTop: 0, this.props.duration);
,
render: function() 
  if (this.state.scrollTop < this.props.offset) 
    return null;
  

  return <a href="#" className="move-top" onClick=this.scrollToTop>↑</a>

这仍然使用 jQuery 来进行实际的滚动。看看this question 没有 jQuery 的滚动。

如果你想让这个组件淡入淡出,你应该用ReactCSSTransitionGroup 包裹它并使用CSS 动画。这记录在React docs。

这是一个JSFiddle 演示。

【讨论】:

【参考方案2】:

在 google 上搜索后,我在 JSFiddle 中找到了您需要的 jQuery 代码。然后,我重新排序了你的 jQuery:

$(document).ready(function() 

  $(window).scroll(function() 
    if ($(this).scrollTop() > 100) 
      $('.move-top').fadeIn();
     else 
      $('.move-top').fadeOut();
    
  );

  $('.move-top').click(function() 
    $("html, body").animate(
      scrollTop: 0
    , 600);
    return false;
  );

);
.container 
  min-height: 1000px;


.move-top 
  position: fixed;
  bottom: 50px;
  right: 100px;
  display: none;
  padding: 10px 15px;
  color: #fff;
  font-weight: 600;
  background: #333;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.2/jquery.min.js"></script>
<h1>Page Header</h1>
<div class="container">
  <p>
    Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor
    in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
  </p>
  <p>
    Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor
    in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
  </p>
  <p>
    Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor
    in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
  </p>
  <p>
    Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor
    in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
  </p>
  <p>
    Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor
    in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
  </p>
  <p>
    Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor
    in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
  </p>
  <p>
    Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor
    in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
  </p>

  <a class="move-top" href="#">↑</a>
</div>
<h3>Page Footer</h3>

【讨论】:

我需要在 reactjs 中简单实现这个。【参考方案3】:

如果你想完全避免使用 jQuery

var Example = React.createClass(
    scrollUp: function () 
        var doc = document.documentElement;
        var top = (window.pageYOffset || doc.scrollTop) - (doc.clientTop || 0);

        if (top > 0) 
            window.scrollTo(0, top - 15)
            setTimeout(this.scrollUp, 10)
        
    ,
    render: function () 
        return (<div><h1>Page Header</h1>
            <div ref="container" className="container">
                <p>
                    Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore
                    et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
                    aliquip ex ea commodo consequat. Duis aute irure dolor
                    in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint
                    occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
                </p>
                <p>
                    Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore
                    et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
                    aliquip ex ea commodo consequat. Duis aute irure dolor
                    in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint
                    occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
                </p>
                <p>
                    Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore
                    et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
                    aliquip ex ea commodo consequat. Duis aute irure dolor
                    in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint
                    occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
                </p>
                <p>
                    Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore
                    et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
                    aliquip ex ea commodo consequat. Duis aute irure dolor
                    in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint
                    occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
                </p>
                <p>
                    Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore
                    et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
                    aliquip ex ea commodo consequat. Duis aute irure dolor
                    in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint
                    occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
                </p>
                <p>
                    Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore
                    et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
                    aliquip ex ea commodo consequat. Duis aute irure dolor
                    in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint
                    occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
                </p>
                <p>
                    Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore
                    et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
                    aliquip ex ea commodo consequat. Duis aute irure dolor
                    in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint
                    occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
                </p>

                <a className="move-top" onClick=this.scrollUp>Up</a>
            </div>
        </div>);
    
);

【讨论】:

请注意window.scrollTo的浏览器兼容性:developer.mozilla.org/en-US/docs/Web/API/Window/scrollTo【参考方案4】:

像这样使用下面的代码:

smoothScroll.scrollTo(ID_OF_DOM_ELEMENT, OPTIONAL_CALLBACK_ON_SCROLL_DONE)

代码:

var smoothScroll = 

    timer: null,

    stop: function () 
        clearTimeout(this.timer);
    ,

    scrollTo: function (id, callback) 
        var settings = 
            duration: 1000,
            easing: 
                outQuint: function (x, t, b, c, d) 
                    return c*((t=t/d-1)*t*t*t*t + 1) + b;
                
            
        ;
        var percentage;
        var startTime;
        var node = document.getElementById(id);
        var nodeTop = node.offsetTop;
        var nodeHeight = node.offsetHeight;
        var body = document.body;
        var html = document.documentElement;
        var height = Math.max(
            body.scrollHeight,
            body.offsetHeight,
            html.clientHeight,
            html.scrollHeight,
            html.offsetHeight
        );
        var windowHeight = window.innerHeight
        var offset = window.pageYOffset;
        var delta = nodeTop - offset;
        var bottomScrollableY = height - windowHeight;
        var targetY = (bottomScrollableY < delta) ?
            bottomScrollableY - (height - nodeTop - nodeHeight + offset):
            delta;

        startTime = Date.now();
        percentage = 0;

        if (this.timer) 
            clearInterval(this.timer);
        

        function step () 
            var yScroll;
            var elapsed = Date.now() - startTime;

            if (elapsed > settings.duration) 
                clearTimeout(this.timer);
            

            percentage = elapsed / settings.duration;

            if (percentage > 1) 
                clearTimeout(this.timer);

                if (callback) 
                    callback();
                
             else 
                yScroll = settings.easing.outQuint(0, elapsed, offset, targetY, settings.duration);
                window.scrollTo(0, yScroll);
                this.timer = setTimeout(step, 10);
            
        

        this.timer = setTimeout(step, 10);
    
;

【讨论】:

【参考方案5】:

我认为react-scroll 值得一提,将其添加到组件的click 处理程序(onClick=this.handleClick

import Scroll from 'react-scroll'

...
Scroll.animateScroll.scrollToTop(options)
...

选项是根据Props/Options指定的对象

【讨论】:

【参考方案6】:

我不建议混合使用 jQuery 和 React/Angular。使用 'react-scroll' 可以轻松完成,如下所示:

import React,  Component  from 'react';
import ReactDOM from 'react-dom';
import  animateScroll as scroll  from 'react-scroll';

class Scrolltotop extends Component 

    ScrollTo() 
        scroll.scrollToTop();
    

    render() 

        return (
            <div className="move-top-wrap">                 
                <div onClick=this.ScrollTo class="move-top">↑</div> 
            </div>
        );

    


export default Scrolltotop;

您可以查看所有basic examples of react-scroll usage here。

您现在可以在任何地方导入和使用该组件。

【讨论】:

以上是关于如何使用 React js 添加平滑滚动返回顶部按钮?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 react-native 中的 onPress 按钮上滚动顶部?

前端 平滑滚动到底部/顶部

顺畅滚动到顶部

RecyclerView - 如何平滑滚动到嵌套滚动视图内某个位置的项目顶部?

Three.js 进阶之旅:页面平滑滚动-王国之泪 💧

返回顶部