我如何包含响应上下文以使我的布局在移动设备上响应?

How can i include Responsive Context to make my layout responsive on mobile?

我在 React 中创建了一个应用程序并使用库 Grommet 来设计我的组件。 我定义了一个主题文件来为不同的移动设备设置断点:

const customBreakpoints = deepMerge(grommet, {
  global: {
    breakpoints: {
      small: {
        value: 768,
        borderSize: {
          xsmall: "1px",
          small: "2px",
          medium: "4px",
          large: "6px",
          xlarge: "12px"
        },
        edgeSize: {
          none: "0px",
          hair: "1px",
          xxsmall: "2px",
          xsmall: "3px",
          small: "6px",
          medium: "12px",
          large: "24px",
          xlarge: "48px"
        },
        size: {
          xxsmall: "24px",
          xsmall: "48px",
          small: "96px",
          medium: "192px",
          large: "384px",
          xlarge: "768px",
          full: "100%"
        }
      },
      medium: { value: 1536 },
      large: {}
    }
  }
});

为了布置按钮,我使用了索环 Box 组件:

const App = () => (
  <Grommet theme={customBreakpoints}>
    <ResponsiveContext.Consumer>
      {size => (
        <div>
          <Box
            direction="column"
            align="center"
            gap="medium"
            pad="small"
            overflow={{
              horizontal: "auto"
            }}
          >
            <Button
              primary
              hoverIndicator="true"
              style={{
                width: "100%"
              }}
              label="Next"
            />
            <Box width="medium" direction="row-responsive">
              <Button
                primary
                icon={<DocumentPdf color="white" />}
                style={{
                  boxSizing: "border-box",
                  background: "red",
                  height: "38px",
                  lineHeight: "24px",
                  fontSize: "18px",
                  fontWeight: 600,
                  paddingLeft: "20px",
                  paddingRight: "20px"
                }}
                label="Export PDF"
              />

              <Button
                primary
                icon={<DocumentPdf color="white" />}
                style={{
                  boxSizing: "border-box",
                  background: "red",
                  height: "38px",
                  lineHeight: "24px",
                  fontSize: "18px",
                  fontWeight: 600,
                  paddingLeft: "20px",
                  paddingRight: "20px"
                }}
                label="Export all"
              />
            </Box>
          </Box>
        </div>
      )}
    </ResponsiveContext.Consumer>
  </Grommet>
);

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

当我 运行 应用程序并在不同设备上检查我当前的 window 时,我得到以下输出:

即使使用 ResponsiveContext.Consumer 并设置 width=size} 它也没有用。

有什么建议吗?

我做了一个Sandbox例子。

按钮不是布局的驱动程序,它们的布局由包装器布局组件控制,在您的情况下,它是 codesanbox 上 Grommet 组件下方的 Box 组件。

Box 组件会自动响应您定义的自定义断点,这似乎按预期工作,也就是说,索环确实提供了精心计算的开箱即用断点定义,您的应用程序无论如何都会将其用作默认断点定义, 因此除非您对自定义断点有特殊要求,否则使用默认断点通常可以解决问题并消除复杂性。

您的代码正在导入 ResponsiveContext,但 ResponsiveContext 没有包装布局组件,也没有使用 size 属性,所以一旦添加这些属性,我认为它会按预期工作。我只用 ResponsiveContext 替换了 div(使用 Box 时不需要 div),并向 Box 添加了 sizewidth 属性,如下所示:

    <ResponsiveContext.Consumer>
      {size => (
        <Box
          direction="column"
          align="center"
          gap="medium"
          pad="small"
          overflow={{
            horizontal: "auto"
          }}
          width={size==="small" ? "200px" : "400px"}
        >
   ...

在您的沙盒中使用上述代码部分将使您更好地了解如何以响应方式控制按钮。您可以根据需要使用 width 道具上的值,目前,它在 'small' 屏幕尺寸上将 Button 的宽度设置为 200px,否则使用 400px(我选择了随机值),您可以随意使用逻辑和值。正如您所建议的,您也可以使用 width={size} ,这会将宽度的大小默认为断点值 ('small'、'medium'、'large'...)

这是完整的代码示例:

import React from "react";
import ReactDOM from "react-dom";
import { Box, Button, Grommet, ResponsiveContext } from "grommet";
import { DocumentPdf } from "grommet-icons";

import { deepMerge } from "grommet/utils";
import { grommet } from "grommet/themes";

import "./styles.css";

const customBreakpoints = deepMerge(grommet, {
  global: {
    breakpoints: {
      small: {
        value: 368,
        borderSize: {
          xsmall: "1px",
          small: "2px",
          medium: "4px",
          large: "6px",
          xlarge: "12px"
        },
        edgeSize: {
          none: "0px",
          hair: "1px",
          xxsmall: "2px",
          xsmall: "3px",
          small: "6px",
          medium: "12px",
          large: "24px",
          xlarge: "48px"
        },
        size: {
          xxsmall: "24px",
          xsmall: "48px",
          small: "96px",
          medium: "192px",
          large: "384px",
          xlarge: "768px",
          full: "100%"
        }
      },
      medium: {
        value: 768,
        borderSize: {
          xsmall: "2px",
          small: "4px",
          medium: "8px",
          large: "12px",
          xlarge: "16px"
        },
        edgeSize: {
          none: "0px",
          hair: "1px",
          xxsmall: "2px",
          xsmall: "3px",
          small: "6px",
          medium: "12px",
          large: "24px",
          xlarge: "48px"
        },
        size: {
          xxsmall: "48px",
          xsmall: "96px",
          small: "192px",
          medium: "384px",
          large: "768px",
          xlarge: "1200px",
          full: "100%"
        }
      },
      large: {}
    }
  }
});

const App = () => (
  <Grommet theme={customBreakpoints}>
    <ResponsiveContext.Consumer>
      {size => (
        <Box
          direction="column"
          align="center"
          gap="medium"
          pad="small"
          overflow={{
            horizontal: "auto"
          }}
          width={size==="small" ? "200px" : "400px"}
        >
          <Button
            primary
            hoverIndicator="true"
            style={{
              width: "100%"
            }}
            label="Next"
          />

          <Button
            primary
            icon={<DocumentPdf color="white" />}
            style={{
              width: "100%"
            }}
            label="Export PDF"
          />

          <Button
            primary
            icon={<DocumentPdf color="white" />}
            style={{
              width: "100%"
            }}
            label="Export all"
          />
        </Box>
      )}
    </ResponsiveContext.Consumer>
  </Grommet>
);

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

希望对您有所帮助。