如何从 Material UI 为我的应用中的 React 添加带有 Back to Top 按钮的 AppBar?

Posted

技术标签:

【中文标题】如何从 Material UI 为我的应用中的 React 添加带有 Back to Top 按钮的 AppBar?【英文标题】:How do I add AppBar with Back to Top button from Material UI for React in my App? 【发布时间】:2020-08-17 23:26:37 【问题描述】:

在 Material UI 的文档中,我找到了这段代码:

import React from 'react';
import PropTypes from 'prop-types';
import AppBar from '@material-ui/core/AppBar';
import Toolbar from '@material-ui/core/Toolbar';
import Typography from '@material-ui/core/Typography';
import  makeStyles  from '@material-ui/styles';
import CssBaseline from '@material-ui/core/CssBaseline';
import useScrollTrigger from '@material-ui/core/useScrollTrigger';
import Box from '@material-ui/core/Box';
import Container from '@material-ui/core/Container';
import Fab from '@material-ui/core/Fab';
import KeyboardArrowUpIcon from '@material-ui/icons/KeyboardArrowUp';
import Zoom from '@material-ui/core/Zoom';

const useStyles = makeStyles((theme) => (
    root: 
        position: 'fixed',
        bottom: theme.spacing(2),
        right: theme.spacing(2),
    ,
));

function ScrollTop(children) 
    const classes = useStyles();
    const trigger = useScrollTrigger(
        target: window ? window() : undefined,
        disableHysteresis: true,
        threshold: 100
    );

    const handleClick = (event) => 
        const anchor = (event.target.ownerDocument || document).querySelector('#back-to-top-anchor');
        if (anchor) 
            anchor.scrollIntoView( behavior: 'smooth', block: 'center' );
        
    ;
    return (<Zoom in=trigger>
        <div onClick=handleClick role="presetation" className=classes.root>
            children
        </div>
    </Zoom>);

export default function BackToTop(children) 
    return (
        <React.Fragment>
            <CssBaseline />
            <AppBar>
                <Toolbar>
                    <Typography variant="h6">Scroll to see button</Typography>
                </Toolbar>
            </AppBar>
            <Toolbar id="back-to-top-anchor" />
            <Container>
                <Box my=2>
                    [...new Array(100)]
                        .map(
                            () => `Cras mattis consectetur purus sit amet fermentum.
                                    Cras justo odio, dapibus ac facilisis in, egestas eget quam.
                                    Morbi leo risus, porta ac consectetur ac, vestibulum at eros.
                                    Praesent commodo cursus magna, vel scelerisque nisl consectetur et.`,
                        )
                        .join('\n')
                </Box>
            </Container>
            <ScrollTop ...children>
                <Fab color="secondary" size="small" aria-label="scroll back to top">
                    <KeyboardArrowUpIcon />
                </Fab>
            </ScrollTop>
        </React.Fragment>
    );

据说这段代码是顶栏,会画Back to top按钮。但我不明白我应该将什么作为children 传递给BackToTop 函数。谁能帮帮我? P.S Code 还包含内容,存储在Box 元素中,仅用于测试。如果我正确理解children 参数的用途,我应该能够使BackToTop 函数独立于任何参数。

【问题讨论】:

【参考方案1】:

您所指的文档部分在这里:https://material-ui.com/components/app-bar/#back-to-top。该演示的代码沙盒版本在这里:https://codesandbox.io/s/r59zg?file=/demo.js。

与文档中的演示相比,您问题中的代码有一些有问题的更改。令人困惑的是,您在几个地方(BackToTop 参数和ScrollTop 参数)将props 重命名为children。文档代码中需要注意的一点是,传递给 BackToTop 的道具从未使用过——它们通过 &lt;ScrollTop ...props&gt; 传递给 ScrollTop,但 ScrollTop 也不使用任何这些道具(而且由于index.js 没有将任何道具传递给BackToTop,它是一个空对象,所以可以用它做的不多)。

这是一个稍微简化的演示版本,用于删除不使用的道具:

import React from "react";
import PropTypes from "prop-types";
import AppBar from "@material-ui/core/AppBar";
import Toolbar from "@material-ui/core/Toolbar";
import Typography from "@material-ui/core/Typography";
import  makeStyles  from "@material-ui/core/styles";
import CssBaseline from "@material-ui/core/CssBaseline";
import useScrollTrigger from "@material-ui/core/useScrollTrigger";
import Box from "@material-ui/core/Box";
import Container from "@material-ui/core/Container";
import Fab from "@material-ui/core/Fab";
import KeyboardArrowUpIcon from "@material-ui/icons/KeyboardArrowUp";
import Zoom from "@material-ui/core/Zoom";

const useStyles = makeStyles(theme => (
  root: 
    position: "fixed",
    bottom: theme.spacing(2),
    right: theme.spacing(2)
  
));

function ScrollTop(props) 
  const  children  = props;
  const classes = useStyles();
  const trigger = useScrollTrigger(
    disableHysteresis: true,
    threshold: 100
  );

  const handleClick = event => 
    const anchor = (event.target.ownerDocument || document).querySelector(
      "#back-to-top-anchor"
    );

    if (anchor) 
      anchor.scrollIntoView( behavior: "smooth", block: "center" );
    
  ;

  return (
    <Zoom in=trigger>
      <div onClick=handleClick role="presentation" className=classes.root>
        children
      </div>
    </Zoom>
  );


ScrollTop.propTypes = 
  children: PropTypes.element.isRequired
;

export default function BackToTop() 
  return (
    <React.Fragment>
      <CssBaseline />
      <AppBar>
        <Toolbar>
          <Typography variant="h6">Scroll to see button</Typography>
        </Toolbar>
      </AppBar>
      <Toolbar id="back-to-top-anchor" />
      <Container>
        <Box my=2>
          [...new Array(25)]
            .map(
              () => `Cras mattis consectetur purus sit amet fermentum.
Cras justo odio, dapibus ac facilisis in, egestas eget quam.
Morbi leo risus, porta ac consectetur ac, vestibulum at eros.
Praesent commodo cursus magna, vel scelerisque nisl consectetur et.`
            )
            .join("\n")
        </Box>
      </Container>
      <ScrollTop>
        <Fab color="secondary" size="small" aria-label="scroll back to top">
          <KeyboardArrowUpIcon />
        </Fab>
      </ScrollTop>
    </React.Fragment>
  );

ScrollTop 中使用的 childrenScrollTop 元素内 JSX 中的子元素。在这种情况下是:

        <Fab color="secondary" size="small" aria-label="scroll back to top">
          <KeyboardArrowUpIcon />
        </Fab>

这会将浮动操作按钮传递给ScrollTop,作为用户滚动时显示的内容,以及点击时将导致页面滚动回顶部的内容。

您问题中的代码有 ScrollTop(children) 而不是 ScrollTop(children) - 即您正在调用整个 props 对象 children 而不是从中获取 children 属性。

【讨论】:

以上是关于如何从 Material UI 为我的应用中的 React 添加带有 Back to Top 按钮的 AppBar?的主要内容,如果未能解决你的问题,请参考以下文章

如何从 Material UI 文本字段中查看密码?

Material UI 中的多行占位符文本

如何防止 material-ui 包覆盖我的应用程序样式?

透明滑动抽屉 Material-UI

从 React 中的 document.createElementNS 创建的 Material UI 图标未正确加载

如何使 React Material-UI 中的 GridList 组件具有响应性