如何使用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,请使用下面的命令。
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端点检索数据。因此,这里是管理应用程序状态的完美场所。
Container 和Layout 组件都被导入到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创建一个响应式的网站。因此,你可以利用这些知识来创建更多高质量的应用程序。