在 React 應用程序中使用 Grommet
已發表: 2022-03-10多年來,隨著幫助開發 React 應用程序的庫的發明,React 生態系統不斷發展。 在本教程中,我們將學習使用 Grommet 為 React 應用程序開發響應式、可訪問性和移動優先的組件。 我們將仔細研究它的核心概念、一些用例,並構建一個簡單的示例。 需要注意的是,Grommet 是開源的,在 GitHub 上有 6.9k 星。
本教程將對有興趣使用 Grommet 在其 React 應用程序中開發響應式組件的讀者有所幫助。 本文需要對 React 和 Styled-components 有基本的了解。
什麼是索環?
Grommet 是一個 React 組件庫,它擁有響應式和可訪問的移動優先代碼組件。 它通過它的組件來做到這一點——這些組件是庫的構建塊。 它們包括佈局、類型、顏色、控件、輸入、可視化媒體和實用程序。 所有索環組件都是內置的,考慮到了可訪問性和響應性。
Grommet 提供對 W3C 規範的支持,這使得它在可訪問性方面得分很高。 它還提供強大的主題和工具,允許您根據項目需要自定義顏色、類型、組件元素和佈局需求。
Grommet 的一些流行替代品包括 tailwindcss 和样式化組件,雖然在開發人員中非常流行,但每個框架在構建應用程序的方法上有所不同。 Grommet 是移動優先、可訪問、響應式和開箱即用的主題,並且支持 W3C 以輕鬆創建 React 應用程序,而 Tailwind CSS 是一個高度可定制和實用的框架,允許開發人員構建應用程序而不受 CSS 的限制,例如其級聯規則。 Styled-components 旨在幫助開發人員編寫可重用的 React 組件,允許我們使用對象文字在 JavaScript 中編寫 CSS 代碼,它還使用組件作為低級樣式構造。
在我們的項目中,我們將在我們的項目中使用 Grommet,因為它具有可定制的組件、可訪問性和主題屬性,這是我們在本教程中繼續進行時所需要的。
使用索環組件
與許多其他組件庫一樣,Grommet 預構建了一些用於佈局和主題的組件,例如 Box、Card 和 Header 組件。 要首先使用,您需要使用 NPM 或 yarn 安裝 grommet 包,如下面的代碼塊。
npm i grommet styled-components
要么:
yarn add grommet styled-components
從上面可以看出我們也安裝了styled-components。 這是因為 Grommet 使用 styled-components 來自定義組件中的樣式; 建議在您的項目中安裝 styled-components。
要在 React 項目中使用 Grommet 組件,您需要導入grommet
。 下面我們構建一個卡片組件來解釋:
import React from 'react'; import { Grommet, Card } from 'grommet'; export default function GrommetExample() { return ( <Card> <CardBody pad="medium">Body</CardBody> <Button icon={<Icons.Favorite color="red" />} hoverIndicator /> </Card> ); }
在上面的代碼塊中,首先將Grommet
和從grommet
包中的Card
組件導入到您的文件中,接下來我們使用我們導入的Card
組件包裝我們的組件。 樣式可以像我們對Button
一樣作為對象添加到 Grommet 組件,也可以使用 styled-components 設置樣式。
讓我們通過查看 Form 組件來了解更多有關 Grommet 組件的示例。
為什麼是索環?
Grommet 的主要目的是改善開發人員的體驗,並通過其移動優先、可訪問和響應式組件以更快的方式構建 React 應用程序。 Grommet 將設計和開發人員工作流程無縫對齊,以創建無縫體驗,讓任何人都可以輕鬆上手。
Grommet 還為開箱即用的屏幕閱讀器提供支持,諸如暗模式之類的主題變體是從開箱即用的themeMode
中獲得的,並且可以使用 React 應用程序中的 themeMode 屬性進行設置,如下所示。
import React from "react"; import { Grommet, Box, Button, Heading, dark } from "grommet"; import { grommet } from "grommet"; const App = () => { const [darkMode, setDarkMode] = React.useState(false); return ( <Grommet full theme={grommet} themeMode={darkMode ? "dark" : "light"}> <Box pad="large"> <Heading level="1">Grommet Darkmode toggle</Heading> <Button label="Toggle Theme" primary alignSelf="center" margin="large" onClick={() => setDarkMode(!darkMode)} /> </Box> </Grommet> ); }; export default App;
在上面的代碼塊中,我們使用themeMode
屬性來添加暗模式。 使用三元運算符,我們檢查頁面是否處於暗模式,我們可以將其切換到亮模式,接下來我們在應用程序中添加了一個用於在亮模式和暗模式之間切換的按鈕,您可以在此處查看 Codesandbox 上的演示。
Grommet 也可以與其他框架一起存在,並且不會添加會影響 React 應用程序中現有組件的全局樣式,函數和样式可以插入到樣式的對象文字中。 Grommet 還具有 Layout 組件,它具有一些 CSS 屬性,例如 flexbox,它還接受所有 flexbox 屬性作為 props。
與許多其他框架不同,Grommet 具有一個大型 SVG 圖標庫,可使用<Icon />
組件訪問。 Grommet 具有用於數據可視化的組件,例如條形圖、地圖甚至進度跟踪器。
今天有幾家公司使用 Grommet 創建現實世界的應用程序,包括 Netflix、IBM、Sony、Samsung、Shopify、GitHub 和 Twilio。
使用索環構建定價組件
現在我們了解了 Grommet 的基礎知識和核心概念,我們將使用 Grommet 組件創建一個定價組件,它應該包含來自 Grommet 庫的 Card、Box 和 Buttons 等組件。
事不宜遲,讓我們開始吧!
設置您的環境
首先,讓我們創建一個裸 React 應用程序,在終端上編寫下面的代碼塊。
create-react-app grommet-app
上面的代碼將使用 create-react-app 包創建一個裸 React 應用程序。 進入項目目錄。
cd grommet-app
接下來是安裝我們在項目中需要的依賴項。
yarn add grommet styled-components
如果您已完成此操作,請使用以下命令啟動項目服務器。
yarn start
對於這個項目,我們需要一個帶有樣式組件的卡片和样式組件。
讓我們在下面創建第一張卡片
import React from "react"; import styled from "styled-components"; export default function GrommetCard() { return ( <> <CardWrapper> <Card left> <Div> <Div> <CardContent> <small>Basic</small> <h1>$588</h1> </CardContent> <CardContent> <p>500 GB storage</p> </CardContent> <CardContent> <p>2 Users Allowed</p> </CardContent> <CardContent> <p>Send Up To 3 GB</p> </CardContent> </Div> <CardButton secondary>LEARN MORE</CardButton> </Div> </Card> </CardWrapper> </> ); }
在上面的代碼塊中,我們使用組件CardWrapper
來包裝我們所有的Card
組件,接下來我們添加了一個新組件CardContent
,它用於包裝每個卡片組件中的所有內容。 CardButton
組件是在 Grommet 上的卡片上使用的按鈕組件。
接下來,讓我們使用 styled-components 為我們的應用程序創建樣式。 在下面寫入文件:
const primaryGradient = "linear-gradient(hsl(236, 72%, 79%), hsl(237, 63%, 64%))"; const CardWrapper = styled.div` display: flex; justify-content: center; align-items: center; height: max-content; margin: 20px; @media all and (max-width: 1240px) { flex-direction: column; } `;
在上面,我們在應用程序中為CardWrapper
定義了一個樣式對象。 讓我們為上面的 Card 組件添加樣式對象。
const Card = styled.div` min-width: 380px; box-shadow: 3px -2px 19px 0px rgba(50, 50, 50, 0.51); border-radius: ${(props) => (props.left ? " 6px 0 0 6px" : props.right ? "0 6px 6px 0" : "6px")}; background: ${(props) => (props.secondary === undefined ? "#fff" : primaryGradient)}; padding: 25px 20px; height: ${(props) => (props.center ? "520px" : "480px")}; display: flex; justify-content: center; align-items: center; @media all and (max-width: 1240px) { margin-bottom: 20px; border-radius: 6px; height: 480px; } @media all and (max-width: 420px) { min-width: 90%; } `;
讓我們為我們的組件添加更多樣式。
const CardButton = styled.div` min-width: 100%; padding: 10px 15px; min-height: 50px; box-shadow: 1px 1px 0 rgba(0, 0, 0, 0.2), 0px 0px 2px rgba(0, 0, 0, 0.2); color: ${(props) => (props.secondary !== undefined ? "#fff" : "#7c7ee3")}; background: ${(props) => (props.secondary === undefined ? "#fff" : primaryGradient)}; text-align: center; margin-top: 25px; display: flex; align-items: center; justify-content: center; font-weight: 600; font-size: 16px; border-radius: 6px; `; const CardContent = styled.div` width: 100%; color: ${(props) => (props.secondary !== undefined ? "#fff" : "#000")}; padding-bottom: 10px; margin-bottom: 10px; border-bottom: 1.3px solid #eee; text-align: center; `; const Div = styled.div` min-width: 100%; `;
完成所有這些後,我們的項目應該類似於下圖。
我們需要使用下面的代碼塊向我們的組件添加更多卡片。
<Card center secondary> <Div> <Div> <CardContent secondary> <small>Premium</small> <h1>$788</h1> </CardContent> <CardContent secondary> <p>75 GB storage</p> </CardContent> <CardContent secondary> <p>4 Users Allowed</p> </CardContent> <CardContent secondary> <p>Send Up To 5 GB</p> </CardContent> </Div> <CardButton>LEARN MORE</CardButton> </Div> </Card> <Card right> <Div> <Div> <CardContent> <small>PRO</small> <h1>$1000</h1> </CardContent> <CardContent> <p>1TB storage</p> </CardContent> <CardContent> <p>Unlimited Users Allowed</p> </CardContent> <CardContent> <p>Send Up To 10 GB</p> </CardContent> </Div> <CardButton secondary>LEARN MORE</CardButton> </Div> </Card> </CardWrapper> </> ); }
在這裡,我們創建了另外兩個卡片組件,使用 styled-components 添加我們自己的自定義組件,並使用我們上面定義的樣式對象來包裝我們的 Grommet 組件並改進樣式。
我們最終的價格卡應用程序應如下圖所示。
在生產中使用 Grommet(建築清單應用程序)
要查看在另一個應用程序中使用 Grommet 的示例,我們將構建一個簡單的應用程序,允許用戶添加、查看和刪除列表項。 我們將使用內置的 React Context API 來管理應用程序的狀態,使用 Grommet 來管理我們的 UI 組件和 styled-components 來設置應用程序的樣式。
同樣,讓我們使用下面的命令初始化一個反應應用程序。
create-react-app list-app
cd 進入項目目錄
cd list-app
yarn add grommet grommet-controls grommet-icons styled-components
在上面的代碼塊中,我們安裝了:
grommet | 我們的 UI 組件庫 |
grommet-controls , grommet-icons | 我們需要安裝以使用 Grommet 的圖標和控件包 |
styled-components | 用於使用標記文字來設置反應組件和索環的樣式 |
構建應用程序上下文
在應用程序中,我們需要在多個組件之間共享用戶數據,以實現我們將使用 Context API。 有了這個,我們可以創建一個 App Context 來保存我們的應用程序的列表和邏輯。 您可以查看這篇文章以了解有關 Context API 的更多信息。
要創建我們的應用上下文,首先在應用程序的src
目錄中創建一個名為context
的文件夾,接下來創建一個名為AppContext.js
的文件,這將是我們所有應用上下文的文件,讓我們在下面的代碼塊中執行此操作:
import React, { createContext, useState } from 'react'; export const Context = createContext(); const AppContext = ({children}) => { const [lists, setLists] = useState([]); const removeList = item => { let newLists = [...lists]; lists.map((list, id) => { return list === item && newLists.splice(id, 1); }); setLists(newLists); }
在上面的代碼塊中,我們從 React 中導入了上下文 API 鉤子createContext
和useState
鉤子,使用useState
組件,我們為我們的應用程序創建了一個中央狀態,這樣做是為了讓該組件可以充當其他的上下文提供者我們應用程序中的組件。 接下來,我們創建了一個名為removeList
的新變量,它接受一個項目作為參數,使用擴展運算符我們正在傳播狀態中的內容並拼接出與我們要刪除的項目相等的對象。
接下來,我們將使用上面的邏輯在我們的應用程序中創建用於添加和刪除列表項的方法,我們在下面的代碼塊中執行此操作:
return ( <Context.Provider value={{ lists, addToLists: (newItem) => setLists([...lists, newItem]), deleteFromList: (item) => removeList(item) }}> {children} </Context.Provider> ) } export default AppContext;
在這裡,我們返回Context.Provider
並接受 children 道具,這樣做是為了讓其他組件能夠訪問我們在 value 道具中傳遞的屬性,我們初始化了lists
對像以接收我們的列表, addToList
方法接受newItem
參數以將新列表添加到我們的應用程序狀態,而deleteFromList
從列表存儲中刪除或刪除項目。
構建列表組件
在本節中,我們將使用 Grommet 為我們的 UI 組件和 styled-components 構建我們的 List 組件以設置我們 UI 的某些部分的樣式。 首先,在我們的應用程序src
目錄中創建一個 components 文件夾,然後在 components 文件夾中,創建一個新文件List.js
並在其中編寫以下代碼。
import React from "react"; import styled from "styled-components"; import { Card, CardBody, Box, Text, Button } from "grommet"; function List(props) { return ( <StyledDiv> <Card> <CardBody className="card_body"> <Box direction="row" className="item_box"> <Text className="text">{props.list}</Text> <Box className="button_box"> <Button onClick={props.deleteList.bind(this, props.list)} className="button" > Delete </Button> </Box> </Box> </CardBody> </Card> </StyledDiv> ); } export default List;
在上面的代碼中,我們首先從 grommet 中導入了 Card、CardBody、Box、Text 和 Button 組件,接下來我們創建了一個 List 組件來接收道具,使用 Grommet 組件我們創建了一個帶有刪除按鈕的卡片組件,該按鈕將自動添加到一個列表。 接下來是在下面為我們的組件設置樣式:
const StyledDiv = styled.div` .button { background-color: #8b0000; color: white; padding: 10px; border-radius: 5px; } .card_body { padding: 20px; margin-top: 20px; } .item_box { justify-content: space-between; } .text { margin-top: auto; margin-bottom: auto; } `;
完成上述操作後,我們的組件應如下圖所示。
構建列表顯示組件
該組件顯示我們添加的所有列表,並在添加新列表時自動生成一個刪除按鈕。
import React from "react"; import List from "./List"; import { Context } from '../context/AppContext'; function ListDisplay() { return ( <Context.Consumer> {(context) => ( <div className="container"> {context.lists.length ? context.lists.map((list, id) => ( <List key={id} list={list} deleteList={context.deleteFromList} /> )) : null } </div> )} </Context.Consumer> ); } export default ListDisplay;
在這個組件中,我們創建了一個ListDisplay
函數,並使用appContext
組件中的Context.Consumer
將其包裝起來,接下來使用div
作為容器標籤,我們從應用上下文中解構了list
和deleteList
方法,通過這樣做我們可以將它們作為道具傳遞。 接下來,我們映射lists
以返回一個新列表,我們可以通過將返回的對像作為道具傳遞給List
組件來構建單個列表。
添加列表後,我們的組件應如下所示:
導航欄組件
這個組件將是我們應用程序的主體,在這裡我們將使用Context.Consumer
來包裹我們的組件,並且與我們的其他組件類似,我們將使用樣式化組件進行樣式化。 讓我們在下面構建這個組件。
import React, { useState } from "react"; import { Heading, Form, TextInput, Button } from "grommet"; import styled from "styled-components"; import { Context } from '../context/AppContext'; function Navbar() { const [value, setValue] = useState(""); return ( <Context.Consumer> {store => ( <StyledDiv className="container"> <Heading className="title">Grommet List App</Heading> <Form onSubmit={() => store.addToLists(value)} className="form-group"> <TextInput className="form" value={value} type="text" onChange={(e) => setValue(e.target.value)} placeholder="Enter item" /> <Button type='submit' className="button">Add to List</Button> </Form> </StyledDiv> )} </Context.Consumer> ); } const StyledDiv = styled.div` .button { margin-top: 10px; background-color: purple; color: white; padding: 10px; border-radius: 5px; } `; export default Navbar;
首先,為了訪問應用程序上下文提供程序中的屬性,我們將組件包裝在Context.Consumer
組件中。 接下來,我們從 Grommet 添加了一個Heading
標籤,然後我們使用addToList
方法創建了一個用於添加列表的輸入表單,該方法接受一個值參數(在我們的例子中,該值是用戶的輸入)。 最後但同樣重要的是,我們添加了一個提交按鈕來處理表單提交。
正確完成後,我們的應用程序應如下所示:
結論
在本文中,我們了解了 Grommet,這是一個考慮到響應性和可訪問性的組件庫。 我們還完成了使用 Grommet 和列表應用程序創建定價組件應用程序的過程。 使用 Grommet 為您的組件和您的下一個 React 應用程序的 UI 需求帶來樂趣。 Grommet 列表應用程序的代碼可以在 Codesandbox 上找到,定價組件可以在這裡找到。
資源
- 索環文檔
- 索環簡介
- React 的 Context API 簡介