如何用Material UI和Next.js创建响应式布局

1,734 阅读4分钟

如何使用Material UI和Next.js创建响应式布局

在构建一个应用程序时,其中一个关键的方面是使其具有响应性。这个功能允许网站或移动应用适应不同的屏幕尺寸或设备。这是因为个人可以通过手机或电脑访问该网站。

在这篇文章中,我们将学习如何创建响应不同设备宽度和断点的布局。我们将使用[Next.js]和[Material UI]进行设计。

前提条件

在阅读这篇文章之前,你应该对以下内容有所了解。

  • React如何工作。
  • 在React组件中,数据是如何作为道具传递的。
  • 如何从远程API端点获取数据。
  • 如何在CSS中使用媒体查询。

目标

使用Material UI和Next.js创建一个响应式网站。该应用程序将从JSONPlaceholder获取测试数据,这是一个虚拟的API。

什么是Material UI?

Material UI是一个基于React的CSS工具框架,使开发者能够创建高质量的用户界面。Material UI可以与Bootstrap相提并论,但其方式更为先进。

由于它是一个基于React的CSS框架,它具有许多组件,可以在React应用程序的任何地方导入。Material UI有多种使用情况,包括布局、输入样式、导航等。

什么是Next.js

Next.js是一个基于React的前端Web框架。它为开发者提供了大量的功能,包括服务器端渲染和静态网站生成。Next.js让开发者免去了从头开始建立一个反应式应用程序的压力。

Next.js和Material UI的设置

为了使用Material UI和Next.js,我们需要将它们作为依赖项安装在我们的React应用程序中。

要安装Next.js,请使用下面的命令。

注意,你需要在你的机器上安装NodeNPM

 npm install next react react-dom

然后,我们可以使用以下命令创建一个Next.js项目。

npx create-next-app

要安装Material UI,你可以在终端键入下面的命令。

npm install @material-ui/core

我们可以使用npm run dev 命令启动dev server

创建web-app

在进一步行动之前,我们需要熟悉一下项目结构。

我们将把我们所有的网页放在pages 文件夹中。例如,pages/index.js 将作为默认的主页。

下面是我们的项目结构。

|--pages
|   |--index.js
|--components
|   |__Layout
|   |   | |--Header
|   |   | |--index.js
|   |   |--index.js
|   |--Card
|      |--index.js
|--container
|--index.js

components 目录下的Layout 文件夹将呈现应用程序的导航栏。Card 文件夹将作为容器组件,与从远程API获取的数据进行映射。

卡片组件作为一个可重复使用的组件,可以被导入到应用程序的任何页面。它利用ReactpropTypes 模块来验证该组件所消耗的数据类型。

// Card.js
import React from "react";
import PropTypes from "prop-types";

const Card = ({ children, className, ...props }) => {
  return (
    <div className={`base-card ${className}`} {...props}>
      {children}
    </div>
  );
};

export default Card;

Card.propTypes = {
  children: PropTypes.node.isRequired,
};

PropType validation 涉及验证被传递给React组件的数据类型,作为 (属性)。如果 对象中设置的条件没有得到满足,JavaScript将抛出一个错误。一个完美的例子是,当我们传递一个数字而不是一个字符串作为一个道具。Props propTypes

Card.propTypes = {
  className: propTypes.string.isRequired; // the prop should be a string
}

header 组件渲染了一个简单的文本,显示应用程序的name 。这个组件被导入到layout/index.js 文件中。

下面是标题组件的代码。

import React from "react";

const Header = () => {
  return (
    <header className={`header`}>
      <h1 className={`text-center`}>Awesome user profiles</h1>
    </header>
  );
};

export default Header;

在这个项目中,主Layout 只接受头组件和children 道具。

children 道具代表UI的其余部分。例如,卡片将显示从API检索的数据。

Layout 组件的代码如下所示。

import React from "react";
import Header from "./Header";
import PropTypes from "prop-types";

const Layout = ({ children }) => {
  return (
    <>
      <Header />
      {children}
    </>
  );
};

export default Layout;

Layout.propTypes = {
  children: PropTypes.node.isRequired, 
};

Container 组件从API端点检索数据。因此,这里是管理应用程序状态的完美场所。

ContainerLayout 组件都被导入到index 页面中。

让我们使用Material UI 来修改Container 组件。我们将使用Grid 组件,让应用程序对所有媒体断点或屏幕尺寸作出响应。

import React, { useState } from "react";
import Card from "../components/Card"; // Importing the card component
import Grid from "@material-ui/core/Grid";  //Importing the Grid component

const Container = () => {  
  const { profiles, setProfiles } = useState([]);

  const getProfiles = () => { //fetching data
    fetch("https://jsonplaceholder.typicode/users")
      .then((response) => {
        setProfiles(response.profiles); //updating state with new information
      })
      .catch((err) => console.log(JSON.stringify(err))); // catching any errors
  };

  useEffect(() => { 
    getProfiles();
  }, []);

  return (
    <section className={style.root}>
      <Grid container spacing={4}>
        {profile.map((users) => {
          return (
            <Grid
              xs={12}
              sm={6}
              lg={4}
              key={users.id}
              className={`cont-card`}
            >
              <Card>
                <div className={style.avatar}>
                  <img
                    src={`https://avatars.dicebear.com/v2/avataaars/{{${users.name}}}.svg?options[mood][]=happy`} //updating image
                  />
                </div>
                <div className={style.details}>
                  <h2 className={`text-center`}>{users.name}</h2>
                  <div className={style.userInfo}>
                    <p>{users.email}</p> // insert infor to card
                    <p>{users.phone}</p>
                    <p>
                      ${users.address.street} ${users.address.suite}
                    </p>
                    <p>
                      <a href={`https://${users.website}`}>{users.website}</a>
                    </p>
                    <p>{users.company.name}</p>
                  </div>
                </div>
              </Card>
            </Grid>
          );
        })}
      </Grid>
    </section>
  );
};

export default Container;

让我们了解一下上述代码片段的作用。

应用程序状态

const { profiles, setProfiles } = useState([]);

上面的代码段管理应用程序或组件的状态。profiles 是一个数组,将保存从API中获取的数据。

取回数据

const getProfiles = () => {
  fetch("https://jsonplaceholder.typicode/users")
    .then((response) => {
      setProfiles(response.profiles);
    })
    .catch((err) => console.log(JSON.stringify(err)));
};

函数getProfiles() ,启动了从API检索数据的过程。它依赖于浏览器的Fetch API。

然后在useEffect() 钩子中调用getProfiles 方法。useEffect() 执行React组件的所有生命周期方法。每次浏览器重新加载时都会触发这个钩子。

useEffect(() => {
  getProfiles(); // calls methods
}, []);

useEffect 钩子里面的数组[] 的目的是防止浏览器从API中连续获取数据。这个过程被称为 "useEffect cleanup"。在我们的例子中,它将防止getProfiles 方法被多次调用。

了解标记。

lg 在上面的Container 组件中,你会注意到xs,sm, 和Grid 组件中的props。这些props是卡片组件的断点。它们使卡片能够被响应。

 <Grid
      xs={12}
      sm={6}
      lg={4}        
      key={users.id}
      className={`cont-card`}
  >         
  • extra small screens (xs)上,卡片应该占据设备的全部宽度。

  • small screen sizes (sm)上,卡片应该占据屏幕宽度的一半。因此,允许在网页上并排排列两张卡片。

  • large screen sizes (lg)上,卡片应占据四列的指定部分。这将允许三张卡片并排堆放。

然后,container 组件被导入到Home 页面容器中,在pages/index.js

import Layout from "../src/Layout";
import Container from "../src/Container";

export default function Home() {
  return (
    <div>
      <Layout>
        <Container />
      </Layout>
    </div>
  );
}

结论

在这篇文章中,我们已经学会了如何使用Next.js和Material UI创建一个响应式的网站。因此,你可以利用这些知识来创建更多高质量的应用程序。