如何用React Hooks和Context API替换Redux 福州小程序开发

如何用React Hooks和Context API替换Redux 福州小程序开发

时间:2020-10-7 作者:gykj
在React中处理共享应用程序状态的最流行方法是使用诸如Redux之类的框架。最近,React团队引入了几个新功能,其中包括React HooksContext API。这两个功能有效地消除了大型React项目的开发人员面临的许多挑战。最大的问题之一是“ prop钻”,这是嵌套组件常见的问题。解决方案是使用像Redux这样的状态管理库。不幸的是,这付出了编写样板代码的代价。但是现在可以用React Hooks和Context API替换Redux。

在本教程中,您将学习一种在React项目中处理状态的新方法,而无需编写过多的代码或安装大量的库-Redux就是这种情况。React挂钩允许您使用函数组件内部的本地状态,而Context API允许您与其他组件共享状态。

先决条件

为了继续学习本教程,您需要熟悉以下主题:

  • 反应
  • 反应钩
  • Redux

您将在此处学习的技术基于Redux中引入的模式。这意味着您需要对进行深入了解,reducers然后actions再继续。我当前正在使用Visual Studio Code,它似乎是目前最受欢迎的代码编辑器(尤其是对于JavaScript开发人员而言)。如果您使用的是Windows,我建议您安装Git Bash。使用Git Bash终端执行本教程中提供的所有命令。Cmder还是一个很好的终端,能够在Windows上执行大多数Linux命令。

您可以在GitHub Repository上访问本教程中使用的完整项目。

关于新的状态管理技术

我们需要在React项目中处理两种状态:

  • 地方政府
  • 全球状态

局部状态只能在定义它们的组件内使用。全局状态可以在多个组件之间共享。以前,定义全局状态需要安装状态管理框架,例如ReduxMobX。随着React v16.3.0的发布,Context API得以发布,它允许开发人员无需安装其他库即可实现全局状态。

React v16.8开始Hooks允许在组件中实现许多React功能,而无需编写类。Hooks为React开发人员编写代码的方式带来了巨大的好处。这包括代码重用和在组件之间共享状态的更简便方法。对于本教程,我们将关注以下React钩子:

  • useState
  • useReducer

useState建议用于处理数字或字符串之类的简单值。但是,在处理复杂的数据结构时,您将需要使用useReducer钩子。对于useState,您只需要一个setValue()函数即可覆盖现有状态值。

对于useReducer,您将要处理一个状态对象,该状态对象以树状结构包含多个具有不同数据类型的值。您需要声明可以更改一个或多个这些状态值的函数。对于数组等数据类型,您需要声明多个不可变的函数来处理添加,更新和删除操作。在本教程的后面部分中,您将看到一个示例。

使用useState或声明状态后useReducer,您需要使用React Context将其提升为全局状态。这是通过使用React库提供的功能创建一个上下文对象来完成的createContext。上下文对象允许状态在组件之间共享,而无需使用道具。

您还需要为上下文对象声明一个上下文提供程序。这允许页面或容器组件订阅上下文对象以进行更改。容器的任何子组件都可以使用该useContext函数访问上下文对象。

现在,让我们看看实际的代码。

设置项目

我们将使用create-react-app快速启动我们的项目:

$ npx create-react-app react-hooks-context-app

接下来,让我们安装Semantic UI React,这是一个基于React的CSS框架。这不是必需的;我只是喜欢创建漂亮的用户界面而无需编写自定义CSS:

yarn add semantic-ui-react fomantic-ui-css

打开src/index.js并插入以下导入:

import 'fomantic-ui-css/semantic.min.css';

这就是我们要开始使用语义UI的项目所需要做的。在下一节中,我们将研究如何使用useState钩子声明状态并将其提升为全局状态。

反例:useState

在此示例中,我们将构建一个简单的计数器演示,该演示由两个按钮组件和一个显示组件组成。我们将介绍一种count状态,该状态将在两个组件之间全局共享。组件将是的子代CounterView,它将充当容器。按钮组件将具有将增加或减少count状态值的按钮。

让我们首先count在名为的上下文文件中定义状态context/counter-context.js。在src文件夹中创建此文件并插入以下代码:

import React, { useState, createContext } from "react";

// Create Context Object
export const CounterContext = createContext();

// Create a provider for components to consume and subscribe to changes
export const CounterContextProvider = props => {
  const [count, setCount] = useState(0);

  return (
    <CounterContext.Provider value={[count, setCount]}>
      {props.children}
    </CounterContext.Provider>
  );
};

我们定义了一个名为的状态count,并将默认值设置为0。所有使用的组件CounterContext.Provider都可以访问count状态和setCount功能。让我们在中定义用于显示count状态的组件src/components/counter-display.js

import React, { useContext } from "react";
import { Statistic } from "semantic-ui-react";
import { CounterContext } from "../context/counter-context";

export default function CounterDisplay() {
  const [count] = useContext(CounterContext);

  return (
    <Statistic>
      <Statistic.Value>{count}</Statistic.Value>
      <Statistic.Label>Counter</Statistic.Label>
    </Statistic>
  );
}

接下来,让我们定义组件,该组件将包含用于增加和减少state组件的按钮。创建文件src/components/counter-buttons.js并插入以下代码:

import React, { useContext } from "react";
import { Button } from "semantic-ui-react";
import { CounterContext } from "../context/counter-context";

export default function CounterButtons() {
  const [count, setCount] = useContext(CounterContext);

  const increment = () => {
    setCount(count + 1);
  };

  const decrement = () => {
    setCount(count - 1);
  };

  return (
    <div>
      <Button.Group>
        <Button color="green" onClick={increment}>
          Add
        </Button>
        <Button color="red" onClick={decrement}>
          Minus
        </Button>
      </Button.Group>
    </div>
  );
}

实际上,useContext由于我们尚未指定Provider,因此该功能将无法使用。现在,通过在中创建一个容器来做到这一点src/views/counter-view.js。插入以下代码:

import React from "react";
import { Segment } from "semantic-ui-react";

import { CounterContextProvider } from "../context/counter-context";
import CounterDisplay from "../components/counter-display";
import CounterButtons from "../components/counter-buttons";

export default function CounterView() {
  return (
    <CounterContextProvider>
      <h3>Counter</h3>
      <Segment textAlign="center">
        <CounterDisplay />
        <CounterButtons />
      </Segment>
    </CounterContextProvider>
  );
}

最后,让我们App.js用以下代码替换现有代码:

import React from "react";
import { Container } from "semantic-ui-react";

import CounterView from "./views/counter-view";

export default function App() {
  return (
    <Container>
      <h1>React Hooks Context Demo</h1>
      <CounterView />
    </Container>
  );
}

现在,您可以create-react-app使用以下yarn start命令启动服务器。浏览器应启动并呈现您的计数器。单击按钮以确保incrementdecrement功能正常运行。

您也可以在CodePen上测试此代码。

让我们进入下一部分,在这里我们将建立一个使用useReducer钩子的高级示例。

联系人示例:useReducer

在此示例中,我们将构建一个用于管理联系人的基本CRUD页面。它由几个演示组件和一个容器组成。还有一个用于管理联系人状态的上下文对象。由于我们的状态树比前面的示例要复杂一些,因此我们必须使用useReducer钩子。

创建状态上下文对象src/context/contact-context.js并插入以下代码:

import React, { useReducer, createContext } from "react";

export const ContactContext = createContext();

const initialState = {
  contacts: [
    {
      id: "098",
      name: "Diana Prince",
      email: "diana@us.army.mil"
    },
    {
      id: "099",
      name: "Bruce Wayne",
      email: "bruce@batmail.com"
    },
    {
      id: "100",
      name: "Clark Kent",
      email: "clark@metropolitan.com"
    }
  ],
  loading: false,
  error: null
};

const reducer = (state, action) => {
  switch (action.type) {
    case "ADD_CONTACT":
      return {
        contacts: [...state.contacts, action.payload]
      };
    case "DEL_CONTACT":
      return {
        contacts: state.contacts.filter(
          contact => contact.id !== action.payload
        )
      };
    case "START":
      return {
        loading: true
      };
    case "COMPLETE":
      return {
        loading: false
      };
    default:
      throw new Error();
  }
};

export const ContactContextProvider = props => {
  const [state, dispatch] = useReducer(reducer, initialState);

  return (
    <ContactContext.Provider value={[state, dispatch]}>
      {props.children}
    </ContactContext.Provider>
  );
};

创建父组件src/views/contact-view.js并插入以下代码:

import React from "react";
import { Segment, Header } from "semantic-ui-react";
import ContactForm from "../components/contact-form";
import ContactTable from "../components/contact-table";
import { ContactContextProvider } from "../context/contact-context";

export default function Contacts() {
  return (
    <ContactContextProvider>
      <Segment basic>
        <Header as="h3">Contacts</Header>
        <ContactForm />
        <ContactTable />
      </Segment>
    </ContactContextProvider>
  );
}

创建演示文稿组件src/components/contact-table.js并插入以下代码:

import React, { useState, useContext } from "react";
import { Segment, Table, Button, Icon } from "semantic-ui-react";
import { ContactContext } from "../context/contact-context";

export default function ContactTable() {
  // Subscribe to `contacts` state and access dispatch function
  const [state, dispatch] = useContext(ContactContext);
  // Declare a local state to be used internally by this component
  const [selectedId, setSelectedId] = useState();

  const delContact = id => {
    dispatch({
      type: "DEL_CONTACT",
      payload: id
    });
  };

  const onRemoveUser = () => {
    delContact(selectedId);
    setSelectedId(null); // Clear selection
  };

  const rows = state.contacts.map(contact => (
    <Table.Row
      key={contact.id}
      onClick={() => setSelectedId(contact.id)}
      active={contact.id === selectedId}
    >
      <Table.Cell>{contact.id}</Table.Cell>
      <Table.Cell>{contact.name}</Table.Cell>
      <Table.Cell>{contact.email}</Table.Cell>
    </Table.Row>
  ));

  return (
    <Segment>
      <Table celled striped selectable>
        <Table.Header>
          <Table.Row>
            <Table.HeaderCell>Id</Table.HeaderCell>
            <Table.HeaderCell>Name</Table.HeaderCell>
            <Table.HeaderCell>Email</Table.HeaderCell>
          </Table.Row>
        </Table.Header>
        <Table.Body>{rows}</Table.Body>
        <Table.Footer fullWidth>
          <Table.Row>
            <Table.HeaderCell />
            <Table.HeaderCell colSpan="4">
              <Button
                floated="right"
                icon
                labelPosition="left"
                color="red"
                size="small"
                disabled={!selectedId}
                onClick={onRemoveUser}
              >
                <Icon name="trash" /> Remove User
              </Button>
            </Table.HeaderCell>
          </Table.Row>
        </Table.Footer>
      </Table>
    </Segment>
  );
}

创建演示文稿组件src/components/contact-form.js并插入以下代码:

import React, { useState, useContext } from "react";
import { Segment, Form, Input, Button } from "semantic-ui-react";
import _ from "lodash";
import { ContactContext } from "../context/contact-context";

export default function ContactForm() {
  const name = useFormInput("");
  const email = useFormInput("");
  // eslint-disable-next-line no-unused-vars
  const [state, dispatch] = useContext(ContactContext);

  const onSubmit = () => {
    dispatch({
      type: "ADD_CONTACT",
      payload: { id: _.uniqueId(10), name: name.value, email: email.value }
    });
    // Reset Form
    name.onReset();
    email.onReset();
  };

  return (
    <Segment basic>
      <Form onSubmit={onSubmit}>
        <Form.Group widths="3">
          <Form.Field width={6}>
            <Input placeholder="Enter Name" {...name} required />
          </Form.Field>
          <Form.Field width={6}>
            <Input placeholder="Enter Email" {...email} type="email" required />
          </Form.Field>
          <Form.Field width={4}>
            <Button fluid primary>
              New Contact
            </Button>
          </Form.Field>
        </Form.Group>
      </Form>
    </Segment>
  );
}

function useFormInput(initialValue) {
  const [value, setValue] = useState(initialValue);

  const handleChange = e => {
    setValue(e.target.value);
  };

  const handleReset = () => {
    setValue("");
  };

  return {
    value,
    onChange: handleChange,
    onReset: handleReset
  };
}

相应地插入以下代码App.js

import React from "react";
import { Container } from "semantic-ui-react";
import ContactView from "./views/contact-view";

export default function App() {
  return (
    <Container>
      <h1>React Hooks Context Demo</h1>
    <ContactView />
    </Container>
  );
}

实施代码后,您的浏览器页面应刷新。要删除联系人,您需要先选择一行,然后点击“删除”按钮。要创建新联系人,只需填写表格并点击“联系人”按钮。

您也可以在CodePen上测试此代码。

查看代码以确保您理解所有内容。阅读我包含在代码中的注释。

概要

我希望这些示例在您了解如何无需Redux的情况下如何在React应用程序中管理共享应用程序状态的过程中为您提供帮助。如果您不使用钩子和上下文API来重写这些示例,那将导致更多的代码。看到不处理道具而编写代码有多容易?

在第二个示例中,您可能已经注意到有两个未使用的状态变量-loadingerror。作为挑战,您可以进一步改进此应用程序以利用它们。例如,您可以实施虚假延迟,并使演示文稿组件显示加载状态。您还可以更进一步,并访问真正的远程API。在此error状态变量可用于显示错误消息。

您现在可能要问自己一个唯一的问题:Redux对将来的项目是否必要?我用这种技术看到的一个缺点是您不能使用Redux DevTool扩展来调试应用程序状态。但是,随着新工具的开发,这种情况将来可能会改变。显然,作为开发人员,您仍然需要学习Redux才能维护旧项目。但是,如果您要开始一个新项目,则需要询问您自己和您的团队,是否真的有必要使用第三方状态管理库。

如何用React Hooks和Context API替换Redux 福州小程序开发

迈克尔·万约克

我编写干净,可读和模块化的代码。我喜欢学习可以提高效率和工作效率的新技术。

Gatsby入门:建立第一个静态站点

想加入Jamstack潮流吗?如果您的回答是肯定的,那么Gatsby可能就是您要找的东西,它是周围最受欢迎的Jamstack静态站点生成器之一。这是我们开始使用盖茨比的指南。

JAM代表JavaScript,API和标记。换句话说,虽然请求/响应周期中站点或应用程序的动态部分由客户端中的JavaScript处理,但所有服务器端进程均使用JavaScript通过HTTPS访问的API进行,并且模板化标记是在部署时间,通常使用静态网站生成器。那就是Jamstack。它性能卓越,扩展成本低廉,并提供更好的安全性和流畅的开发人员体验。

为什么要使用静态网站

静态站点模型并不适合所有类型的项目,但是当它适用时,它具有许多优点。这里有几个。

速度

首次发出请求时,网站在浏览器中加载所需的时间是用户体验的重要因素。用户很快就会不耐烦,并且只有在连接速度较慢时情况才会变得更糟。缺少数据库调用和预先生成的内容使静态站点真正快速加载。

静态站点由静态文件组成,可以使用内容分发网络(CDN)轻松地在全球范围内提供服务。这使得可以利用更靠近发出请求的数据中心。

简化托管

可以快速设置静态站点的托管。因为没有数据库或服务器端代码,特殊语言或框架来支持,所以托管所需要做的就是提供静态文件。

更好的安全性

没有服务器端代码或数据库,黑客就无法进行黑客攻击。毫无疑问,可以通过安全修补程序和补丁使服务器保持最新状态。所有这些都意味着您在网站安全方面更加放心。

更好的开发人员体验

使用Netlify或Vercel这样的托管公司来设置您的静态网站非常简单,并且通过持续部署,您只需将更改推送到您选择的代码存储库中,这些更改就会立即反映在实时版本中。

什么是盖茨比?

Gatsby是当今构建网站最流行的工具之一。它不仅仅是静态站点生成器。实际上,它是“用于创建网站和应用程序的基于反应的开源框架。” 由于Gatsby是在React之上构建的,因此所有React的优势就在您的指尖,这使您可以利用此强大的库在交互式静态网站中构建交互式组件。Gatsby也是GraphQL内置的,因此您可以查询数据并将其以任何您希望的方式显示在您的网站上。

安装Gatsby并创建您的项目

Gatsby是使用webpack组合在一起的,但是您不必担心复杂的设置操作;Gatsby CLI将为您处理一切。

对于本教程,我假设您在本地安装了Node.js。如果不是这种情况,请转到Node主页并为您的系统下载正确的二进制文件。或者,您可以考虑使用版本管理器来安装Node。我们这里有一个使用版本anager的教程。

Node与Node软件包管理器npm捆绑在一起,我们将使用它来安装一些将要使用的库。您可以在此处了解有关使用npm的更多信息

您可以通过从命令行发出以下命令来检查两者是否均已正确安装:

node -v
> 12.18.4

npm -v
> 6.14.8

您需要做的第一件事是安装Gatsby CLI。此npm软件包可让您在几秒钟内创建一个Gatsby网站。在您的终端中,输入:

npm install -g gatsby-cli

在计算机上安装了Gasby CLI之后,您可以继续创建网站。我称它为sitepoint-demo,但是您可以随意调用它。在您的终端中,键入:

gatsby new sitepoint-demo

一旦Gatsby CLI安装了所有必需的文件并对其进行了适当的配置,您将拥有一个功能齐全的Gatsby网站,可以自定义和构建该网站。要访问它,请移至该sitepoint-demo文件夹:

cd sitepoint-demo

并启动本地服务器:

gatsby develop

如何用React Hooks和Context API替换Redux 福州小程序开发

为了快速启动并运行一个网站,盖茨比利用了几个正式的入门模板以及由强大社区提供的入门工具。您刚创建的网站使用盖茨比默认启动器,但是您可以在盖茨比网站上找到更多的信息。

如果要使用与默认启动程序不同的启动程序,则需要按照以下模式在命令行中指定其URL:

gatsby new [SITE_DIRECTORY_NAME] [URL_OF_STARTER_GITHUB_REPO]

例如,假设您想要网站的Material Design外观。最快的创建方法是通过在终端中键入以下命令来使用Gatsby Material Starter:

gatsby new sitepoint-demo https://github.com/Vagr9K/gatsby-material-starter

大!现在,让我们看看全新的Gatsby项目中的文件。

Gatsby网站内的游览

/src/目录是一个不错的起点。这是您会发现的。

pages 目录

/src/pages/目录包含您网站的页面。每个页面都是一个React组件。例如,您网站的主页代码位于其中,/pages/index.js如下所示:

import React from "react"
import { Link } from "gatsby"
import Layout from "../components/layout"
import Image from "../components/image"
import SEO from "../components/seo"

const IndexPage = () => (
<Layout>
  <SEO title="Home" />
  <h1>Hi people</h1>
  <p>Welcome to your new Gatsby site.</p>
  <p>Now go build something great.</p>
  <div style={{ maxWidth: `300px`, marginBottom: `1.45rem` }}>
    <Image />
  </div>
  <Link to="/page-2/">Go to page 2</Link>
  <Link to="/using-typescript/">Go to "Using TypeScript"</Link>
</Layout>
)

export default IndexPage

这是React组件的典型代码。

组件使您可以将UI分成独立的,可重用的部分,并单独考虑每个部分。…从概念上讲,组件就像JavaScript函数。它们接受任意输入(称为“ props”),并返回描述应该在屏幕上显示的内容的React元素。— React文档

components 目录

在该/src/components/目录中,您可以找到网站的常规组件。默认启动器带有以下组件:标头(header.js),图像(image.js),布局(layout.js)和SEO(seo.js)。您可以自定义这些组件,然后将自己的组件添加到同一目录中。

现在,您可以开始对新站点进行更改,并根据自己的喜好对其进行自定义。

如何对盖茨比站点进行更改

让我们来修改首页上显示的消息。pages/index.js在您的代码编辑器中打开,然后用以下段落替换<h1>标记下的两个段落:

<p>Welcome to my SitePoint Demo Site!</p>

当然,您可以在<p>标签之间添加任何文本。

一旦您点击Save,由于Gatsby的热重载开发环境,您的更改将立即显示在浏览器中。这意味着,当您开发Gatsby网站时,页面会在后台被查看,因此在保存工作时,更改将立即可见,而无需刷新页面或重新启动浏览器。

通过Gatsby,可以轻松添加新页面。例如,让我们通过about.js/pages/目录内创建一个新文件来添加关于页面,然后输入以下内容:

import React from "react"

const AboutPage = () => <h1>About Me</h1>

export default AboutPage

上面的代码是一个React功能组件,它显示一些文本。

保存您的工作并导航到http:// localhost:8000 / about,您应该<h1>在屏幕上看到“关于我”标题。

您可以使用Gatsby Link组件从主页快速链接到新的About页面。要查看其工作原理,请index.js在代码编辑器中打开并在</Layout>结束标记之前找到以下代码:

<Link to="/page-2/">Go to page 2</Link>

接下来,将to属性的值替换为,/about/并将“转到第2页”文本替换为About

<Link to="/about/">About</Link>

保存您的工作,您应该在屏幕上看到新的链接。单击关于链接,您将立即进入关于页面。

Gatsby使用Link组件进行内部链接。对于外部链接,您应该使用旧的<a>标记,就像在常规的常规HTML网站上那样。

现在,让我们通过更改几种样式来试验Gatsby网站的外观。

设置盖茨比网站的样式

Gatsby提供了许多将样式规则应用到您的网站的选项。

全局样式表

一种常见的选择是使用.css包含适用于整个网站的规则的全局文件。首先,在/styles/目录内添加一个目录/src/并向其中添加global.css文件:/src/styles/global.css。您可以自由选择目录和样式表文件的名称。在内部global.css,添加以下CSS声明,该声明将应用于整个网站:

body {
  background-color: yellow;
}

现在,保存您的工作。糟糕,没有任何反应!仍然没有。要使其正常工作,您需要采取额外的步骤。gatsby-browser.js在代码编辑器中打开并导入刚创建的样式表:

import "./src/styles/global.css"

回到浏览器,您应该看到网站的背景颜色变成了亮黄色。虽然不是理想的颜色选择,但它确实可行!

具有共享布局组件的全局样式

尽管添加全局样式表并将其导入到gatsby-browser.js工作中效果很好,但向Gatsby网站添加全局样式的推荐方法是使用共享的布局组件。Gatsby Default Starter随该组件及其相关样式表提供了开箱即用的功能。

要查看其工作原理,让我们从中删除以上import语句gatsby-browser.js并保存文件。您应该看到您网站的背景恢复为白色。然后,打开layout.jslayout.css在代码编辑器中(您会在components/目录中找到这两个文件)。

在的顶部layout.js,注意import语句,该语句使其中包含的CSS规则layout.css可用于共享的Layout组件,因此可用于整个网站:

import "./layout.css"

在中layout.css,找到body元素的CSS声明。它应该在第8行附近。这看起来像:

body {
  margin: 0;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  color: hsla(0, 0%, 0%, 0.8);
  font-family: georgia, serif;
  font-weight: normal;
  word-wrap: break-word;
  font-kerning: normal;
  -moz-font-feature-settings: "kern", "liga", "clig", "calt";
  -ms-font-feature-settings: "kern", "liga", "clig", "calt";
  -webkit-font-feature-settings: "kern", "liga", "clig", "calt";
  font-feature-settings: "kern", "liga", "clig", "calt";
}

现在为背景颜色添加一个规则,如下所示:

background-color: yellow;

保存您的工作,您应该看到网站的背景颜色再次变为黄色。

组件范围的样式:CSS模块

一个CSS模块是所有类名和动画名称默认局部范围的CSS文件。

使用CSS模块,您的样式仅适用于特定组件,这有助于使组件保持独立,因此易于维护和重用。

CSS模块与Gatsby捆绑在一起,开箱即用,文档通常建议这种向Gatsby组件和React组件添加样式的方式。

请按照以下步骤将花式段落组件添加到“关于”页面。

创建花式段落组件

/components/基于Gatsby Default Starter的项目的目录内,创建一个文件并调用它fancy-paragraph.js

fancy-paragraph.js在代码编辑器中打开,然后输入以下代码:

import React from "react"
import fancyParagraphStyles from "./fancy-paragraph.module.css"

const FancyParagraph = (props) => <p className={fancyParagraphStyles.fancy}>{props.paragraphText}</p>

export default FancyParagraph

这是一个简单的React功能组件—除了导入我们尚未创建的花哨段落CSS模块的语句外,没有什么新内容。

该组件使用fancy-paragraph模块中包含的样式作为className属性内的值。如您所见,该值看起来非常像一个常规JavaScript对象.fancy,该对象使用类的名称作为fancyParagraphStyles对象的属性。您将在CSS模块中编写此类的样式。

创建花式段落CSS模块

在内部/components/,创建另一个文件并调用它fancy-paragraph.module.css。打开此文件,并根据自己的喜好.fancy任何方式设置类的样式。这只是普通的CSS。这是我的样子:

.fancy {
  font-size: 1.5rem;
  text-align: center;
  line-height: 1.2;
  padding: 0.5rem;
  color: #fff;
  background-color: rebeccapurple;
  font-weight: 800;
  font-style: italic;
  text-transform: uppercase;
}

现在,您可以FancyParagraph在Gatsby网站上的任何地方使用具有精美样式的组件了。

让我们在“关于”页面中添加一段漂亮的段落。

将花式段落组件添加到“关于”页面

首先将这两个导入语句添加到您的“关于”页面中,即已经存在的React导入下方:

import Layout from "../components/layout"
import FancyParagraph from "../components/fancy-paragraph"

上面的代码片段使您将在“关于”页面中使用的“盖茨比布局”组件和刚刚创建的“花式段落”组件可用于“关于”页面。

接下来,修改您的AboutPage功能组件,如下所示:

const AboutPage = () => (
<Layout>
 <h1>About Me</h1>
 <FancyParagraph paragraphText="Styled with CSS Modules." />
</Layout>
)

您的新组件就像其他任何React组件一样工作。只需将它拍在页面上的确切位置,即可完成操作。这个特定的组件利用React道具使段落文本更加动态。

保存您的工作并导航到“关于”页面,您将在其中看到所有精美的段落。我的看起来像这样:

如何用React Hooks和Context API替换Redux 福州小程序开发

任务完成!

组件范围的样式:内联样式

可以使用JS对象形式的内联CSS样式。

您的基于Gatsby Default Starter的项目将展示该技术的实际应用。例如,index.js在编辑器中打开并在IndexPage组件内部找到以下代码:

<div style={{ maxWidth: `300px`, marginBottom: `1.45rem` }}>
  <Image />
</div>

请注意CSS样式如何应用于<div>包含该Image组件的:样式采用JS对象的形式,其中CSS属性名称是键,而CSS值是它们的对应值。

另外,请注意复合CSS属性名称如何删除破折号(-)并改用camelCase约定-例如marginBottom,而不是CSS margin-bottom

向Gatsby网站添加内容

使用Gatsby进行构建具有额外的优势,即可以从几乎任何地方抓取数据。因此,您不仅可以构建通常依赖Markdown的静态站点,而且您的团队可以使用自己选择的后端轻松管理内容。

大量专用插件使Gatsby能够从多个来源(例如文件系统,API,WordPress等)中提取数据,并将数据合并到一个可以馈送到您的网站的数据层中。

对于简单的网站,也可以绕过Gatsby的数据层并填充您的网站,而无需使用GraphQL或任何源插件。这种方法也称为非结构化数据方法,它允许您获取数据并createPagecreatePagesAPI内部的操作中使用它。尽管从API提取数据对于JavaScript开发人员来说已经足够熟悉,因此可能比使用GraphQL更具吸引力,但缺点是,放弃Gatsby数据层还意味着放弃其提供的许多好处-例如性能,开发过程中的热重装,快速的图像优化等等。

如果您想了解有关非结构化数据方法的更多信息,请查看此GitHub存储库

在Gatsby页面中手动输入GraphQL查询

如果您有一两个页面的内容很少变化,几乎没有变化,您甚至可以将文本直接编码为Gatsby页面,就像我们在上面的演示中一样。

如果您需要提取诸如站点标题和描述之类的简单数据,则可以直接在页面中输入GraphQL查询。为此,它有助于熟悉GraphiQL,这是一个GraphQL IDE(集成开发环境),用于创建可在http:// localhost:8000 / ___ graphql上访问的GraphQL查询。

假设您要在页面上显示网站标题。首先,确保标题已经在内gatsby-config.js。我的看起来像这样;您可以输入喜欢的任何标题或保留默认标题:

module.exports = {
  siteMetadata: {
    title: `SitePoint Demo Gatsby Site`,
    ...
  },
  ...

接下来,借助GraphiQL构建GraphQL查询。最后,对入门页面的第2页(src/pages/page-2.js)进行以下更改,现在应如下所示:

const SecondPage = ({data}) => (
  <Layout>
    <SEO title="Page two" />
    <h1>Welcome to {data.site.siteMetadata.title}</h1>
    <p>I have used a GraphQL query</p>
    <Link to="/">Go back to the homepage</Link>
  </Layout>
)

export const query = graphql`
  query testQuery {
    site {
      siteMetadata {
        title
      }
    }
  }
`
export default SecondPage

请注意,我们正在将一个dataprop传递给组件,其中包含GraphQL查询的结果。

重新启动服务器,然后您将能够看到第2页(http:// localhost:8000 / page-2 /)上显示的站点标题。

如何用React Hooks和Context API替换Redux 福州小程序开发

但是,仅当管理内容的人员熟悉编码时,此方法才有意义。此外,如果您有一天决定更改文本,则必须去搜索项目目录中的页面并手动替换内容。

您可以在Gatsby docs上阅读有关此方法的所有详细信息。

从文件系统中提取数据 福州小程序开发

您可以使用gatsby-source-filesystem插件从本地文件系统向Gatsby应用程序中获取数据。使用诸如Jekyll或Hugo之类的静态网站生成器的人们可能熟悉这种方法。

Gatsby默认启动程序已安装此插件,您可以通过gatsby-config.js在代码编辑器中打开来轻松进行验证:

plugins: [
    `gatsby-plugin-react-helmet`,
    {
      resolve: `gatsby-source-filesystem`,
      options: {
        name: `images`,
        path: `${__dirname}/src/images`,
      },
    }, ...

在获取数据之后,您将需要一个转换器插件来帮助您将文件节点转换为可在站点中使用的各种数据类型,例如,gatsby-transformer-json用于JSON数据,gatsby-transformer-remark用于Markdown文件等。

在Gatsby文档的这一部分中找到所有详细信息。

如果您选择Markdown文件作为Gatsby网站的数据源,则可以选择使用gatsby-plugin-mdxGatsby插件(将MDX支持添加到您的网站)将JSX可重用组件嵌入文本中。好处如下:

这在内容驱动的站点中非常有用,在这些站点中您希望能够引入图表或警报之类的组件而无需配置插件。它着重于配置而不是配置,并通过交互式博客文章,文档设计系统或具有沉浸式或动态交互的长篇文章而真正令人眼前一亮。— Gatsby docs

无头CMS

CMS代表内容管理系统。传统的CMS同时提供后端和前端功能。无头或解耦的CMS仅将其自身限制在后端,因此将所有前端问题留给了开发人员。这种安排对于像Gatsby这样的网站生成器来说是理想的选择,因为它允许内容团队成员仍然使用他们喜欢的管理界面,而开发人员则可以充分利用使用Gatsby,React和GraphQL的好处。

流行的CMS平台(如WordPress,Drupal,Contentful,Sanity等)提供了无用的支持,而Gatsby生态系统提供了合适的插件和指南来帮助您进行集成。

查看Gatsby文档中的这篇文章,以了解有关从所选CMS中提取数据的更多信息。

部署Gatsby网站

有一些公司使托管静态网站变得超级快速和便捷。其中最受欢迎的是:

  • Netlify
  • 亚马逊S3
  • GitHub页面
  • Firebase托管

部署盖茨比网站以进行Netlify

让我们使用Netlify来启动您全新的盖茨比网站。Netlify提供了“结合了全球部署,持续集成和自动HTTPS的多合一工作流程”。

它非常适合托管静态网站。

首先,您需要创建Gatsby项目的生产版本。为此,请在终端中输入以下命令:

gatsby build

现在,您有一个名为的文件夹,public其中包含您的网站需要在浏览器中运行的所有静态文件。

下一步包括将Gatsby项目放入GitHub之类的存储库中。Netlify支持GitHub,GitLab或Bitbucket:每次将更改推送到代码时,Netlify都会使用您选择的工具运行构建,并将结果部署到其快速加载的CDN中。

首先,只需登录到Netlify,从Git中选择新建站点,选择存储库,输入构建命令和公用文件夹的名称,然后单击部署站点

您可以在Gatsby docs网站上的本文中详细查看部署过程。

恭喜,您的盖茨比网站上线了!

有关构建过程的更多信息

在部署之前运行build命令会创建由Gatsby支持的网站的生产版本,并具有高性能和出色的用户体验所需的所有必要优化。Gatsby在此过程中创建的静态HTML页面又被重新水化为React应用程序。这意味着,当盖茨比页面运行到网络浏览器中时,将下载JavaScript代码,从而启用DOM操作等。换句话说,您的网站成为了功能完善的React应用。

您可以阅读Gatsby文档上的详细信息。

盖茨比云

Gatsby的创始人Kyle Mathews在2019年宣布推出Gatsby Cloud。用他的话说,盖茨比云是

一个稳定,可信赖的工具的商业平台,使网站创建者可以构建更好的网站。盖茨比云通过可互操作的即用型解决方案增强了我们的内容网格平台,从而可以更快地启动网站并推动业务成功。—宣布盖茨比云

换句话说,盖茨比云是基于云的基础架构,可在您创建,更新和部署盖茨比网站时带来大量好处。功能包括:

  • Cloud Quickstart,使非技术用户可以使用CMS,一些虚拟内容和Gatsby启动器在几分钟内创建项目。
  • 实时预览,非常适合实时和在上下文中预览更改,从而促进在您网站上工作的团队成员之间的沟通和协作。
  • CMS Integrations,它快速而轻松,利用了可用于数百种内容管理系统和API的插件
  • 增量构建Incremental Builds)是2020年4月引入的Gatsby Cloud功能。当您选择的CMS中的数据发生变化时,增量构建将仅重建所需的内容,从而显着提高性能。

还有更多……

盖茨比插件

盖茨比的许多超级能力都来自插件。Gatsby插件是Node.js软件包,您可以使用npm将其安装在项目中。盖茨比生态系统提供了大量的插件,可让您执行几乎所有操作。我已经谈到了插件的作用,这些插件可以从多个来源获取数据并准备由Gatsby网站使用,但是也有一些插件可以为主题添加预打包功能,自动集成第三方服务(例如Google Analytics(分析))从React组件创建页面,处理SCSS / Sass文件等等。

如果JavaScript是您的头等大事,那么您也可以尝试创建自己的插件。请查看Gatsby插件创作页面以获取更多详细信息。

后续步骤和资源

要真正掌握Gatsby,请访问其网站并查看官方教程文档。我认为他们是一流的。

另外,为了充分利用Gatsby,我建议您能熟练使用GraphQL处理数据。充分利用GraphQL网站上的出色教程

最后,请确保您查看我们的Jamstack Foundations集合,在其中可以找到我们关于Jamstack的指南,以及精选的Gatsby等Jamstack工具,这些工具可以最大程度地帮助您学习。

版权所有:https://www.eraycloud.com 转载请注明出处