React开发人员的五个最佳组件框架
有很多方法可以使代码结构化,使其易于阅读,并且每个人都有自己的方式到达那里。问题就变成了,有没有最好的方法呢?
在本文中,我将讨论针对React开发人员的五个最常见的最佳实践。React的设计旨在按照您所需的方式进行定制-这是没有根据的!因此,如果这五个“最佳实践”场景不适合您,那么完全可以找到自己的方法。我希望您能摆脱别人目前正在“思考中的思考”的方式。
我们将讨论的最佳实践是:
- 目录组织
- 组件和关注点分离
- 处理状态
- 抽象化
- 命名约定
目录组织
React文档提到,通常有两种主要方法来组织React应用程序:按功能或路由分组和按文件类型分组。这里的关键是不要考虑太多。
如果从较小的应用程序开始,则可以按照适合自己的方式自然地组织代码。请记住,React并非自以为是,所以事情的结构由100%决定。只要您对文件的组织方式有一个逻辑上的解释,那其实并不重要。
但是,由于React文档提到了这两种组织策略,因此让我们看一下每种策略以了解它们的结构。假设我们有一个电子商务应用程序,该应用程序具有用户,产品列表,详细的产品页面,购物车和结帐流程。
功能如何布置?
按功能分组
根目录是src
目录,它是React应用程序中两个基本目录之一(公用文件夹是另一个)。在src
目录中,我们将在文件夹的根目录中包含基本文件App.js
和index.js
文件。然后,我们将为您的应用程序中的每个功能嵌套目录。
就事物的组织方式而言,您的举动可能会有所不同:它可能具有更多目录,更少目录,甚至可能进一步嵌套到组件,样式和测试中。
src/ App.js App.css App.test.js index.js global/ ⇐ items that are in common with entire application AppContext.js ThemeContext.js UserContext.js Button.js cards/ index.js Cards.css Cards.js Card.css Card.js Card.test.js detailed-product/ DetailedProduct.css DetailedProduct.js DetailedProduct.test.js checkout/ ReviewOrder.css ReviewOrder.js ReviewOrder.test.js ShoppingCart.css ShoppingCart.js ShoppingCart.test.js user/ index.js User.css User.js User.test.js
以下是一种约定。如果文件按文件类型分组,组织将如何看待?
按文件类型分组
根目录仍然是src
目录。客户端将看到呈现到屏幕的所有内容仍保留在此文件夹中。和以前一样,我们将App.js
and index.js
文件保留在该目录的根目录中,然后具有代表应用程序组成部分的目录:组件,上下文,css,hook和测试。
src/ App.js index.js components/ App.css Card.js Cards.js ConfirmationPage.js DetailedProduct.js Footer.js Navbar.js ReviewOrder.js Settings.js ShoppingCart.js User.js context/ AppContext.js ThemeContext.js UserContext.js css/ Card.css Cards.css ConfirmationPage.css DetailedProduct.css Footer.css Navbar.css ReviewOrder.css Settings.css ShoppingCart.css User.css hooks/ useAuth.js useAxios.js ...other custom hooks tests/ App.test.js Card.test.js Cards.test.js ConfirmationPage.test.js DetailedProduct.test.js Footer.test.js Navbar.test.js ReviewOrder.test.js Settings.test.js ShoppingCart.test.js User.test.js
与以前一样,项目的设置方式取决于您的应用程序以及实现方式。这里的基本结构取决于文件的类型,仅此而已。最终,应该使文件结构更容易浏览。您的操作方式取决于您。
组件和关注点分离
在使用React Hooks之前,很容易发现什么是有状态类组件还是表述性功能组件。一些开发人员也将它们称为“智能”组件与“哑”组件。当然,智能组件是承载状态和处理逻辑的组件,而哑组件是纯粹接受分配给它们的道具的组件。
在React Hooks出现和Context API更新之后,大多数事物都可以被视为功能组件,这引发了关于何时分离包含本地状态的组件,不包含本地状态的组件以及如何处理的讨论。
最终,由您和/或您的团队决定如何构造设计模式,但是最佳实践倾向于使逻辑和局部状态组件与静态组件保持独立。
处理状态和道具
React应用程序中的数据流非常重要。有两种处理数据的方式:使用状态或将状态作为道具传递。让我们看一下最佳实践。
处理状态时,无论是在上下文API中是全局的还是在本地中,都不得通过使用新值在state上重新分配属性来直接对其进行更改:
addOne = () => { //Don’t use this!!!! this.state.counter += 1; }
而是在处理类组件中的状态时,使用该this.setState()
方法来更新状态。
import React from "react"; import "./styles.css"; class Counter extends React.Component{ constructor(props) { super(props); this.state = { counter: 0 } } addOne = () => { this.setState({counter: this.state.counter + 1}) } subtractOne = () => { this.setState({counter: this.state.counter - 1}); } reset = () => { this.setState({ counter: 0 }); } render() { return ( <div className="App"> <h1>Simple React Counter</h1> <h2>{this.state.counter}</h2> <button onClick={this.addOne}> + </button> <button onClick={this.reset}> Reset </button> <button onClick={this.subtractOne}> - </button> </div> ); } } export default Counter;
使用React Hooks时,将使用您命名的任何set
方法:
import React, { useState } from "react"; import "./styles.css"; export default function App(){ const [ counter, setCounter ] = useState(0); const addOne = () => { setCounter(counter + 1) } const subtractOne = () => { setCounter(counter - 1); } const reset = () => { setCounter(0); } return ( <div className="App"> <h1>Simple React Counter</h1> <h2>{counter}</h2> <button onClick={subtractOne}> - </button> <button onClick={reset}> Reset </button> <button onClick={addOne}> + </button> </div> ); }
道具
当处理道具并将状态传递给要使用的其他组件时,可能会出现一个点,您需要将道具传递五个孩子。这种将道具从父母代传给孩子几代的方法称为道具钻探,应该避免。
虽然如果您将道具传递给下一代,代码肯定会起作用,但它容易出现错误,并且数据流可能很难遵循。最好是如果需要让子级访问几代后的状态,则应该使用Redux或Context API(目前使用Context API是更简单,更可取的方式)为全局状态管理创建某种设计模式。
抽象化
对可重用性做出积极反应。在谈论React最佳实践时,抽象这个词经常出现。抽象意味着大型组件或应用程序的某些部分可以被拿走,制成自己的功能组件,然后导入到较大的组件中。使组件尽可能地简单,通常使其仅用于一个目的,这增加了代码可重用的机会。
在上面创建的简单计数器应用程序中,有机会从App组件中抽象出一些元素。可以将按钮抽象为它们自己的组件,在其中我们将方法和按钮标签作为道具传递给他们。
应用程序的标题和标题也可以包含在它们自己的组件中。在我们将所有内容抽象化之后,App Component可能看起来像这样:
import React, { useState } from "react"; import { Button } from "./Button"; import { Display } from "./Display"; import { Header } from "./Header"; import "./styles.css"; export default function App(){ const addOne = () => { setCounter(counter + 1) } const subtractOne = () => { setCounter(counter - 1); } const reset = () => { setCounter(0); } const initialState = [ {operation: subtractOne, buttonLabel:"-"}, {operation: reset, buttonLabel: "reset"}, {operation: addOne, buttonLabel: "+"} ] const [ counter, setCounter ] = useState(0); const [ buttonContents, ] = useState(initialState) return ( <div className="App"> <Header header="Simple React Counter"/> <Display counter={counter}/> {buttonContents.map(button => { return ( <Button key={button.operation + button.buttonLabel} operation={button.operation} buttonLabel={button.buttonLabel} /> ) })} </div> ); }
抽象的主要目的是使子组件尽可能通用,以便可以按您需要的任何方式对其进行重用。应用程序组件应仅包含特定于应用程序的所有信息,并且仅呈现或返回较小的组件。
命名约定
React中有三个主要的命名约定,应被视为最佳实践。
- 组件应使用PascalCase –也应使用 camelCase大写,并以其功能命名,而不是以特定的应用程序功能命名(以防稍后更改)。
- 需要密钥的元素应该是唯一的,非随机的标识符(例如单个卡片或CardDeck或List中的条目)。最佳做法是不要仅将索引用于键。具有由两个不同的对象属性串联而成的键分配是合法的。
密钥的基本目的是存储基本信息,以便React可以了解应用程序中发生的变化。
key={button.operation + button.buttonLabel}
- 方法应在camelCase中,并应根据其功能命名,而不应特定于应用程序。出于与PascalCase中组件相同的原因,应该为它们的目的而不是在应用程序中的功能来命名方法。
1. 本站资源转自互联网,源码资源分享仅供交流学习,下载后切勿用于商业用途,否则开发者追究责任与本站无关!
2. 本站使用「署名 4.0 国际」创作协议,可自由转载、引用,但需署名原版权作者且注明文章出处
3. 未登录无法下载,登录使用金币下载所有资源。
IT小站 » React开发人员的五个最佳组件框架
常见问题FAQ
- 没有金币/金币不足 怎么办?
- 本站已开通每日签到送金币,每日签到赠送五枚金币,金币可累积。
- 所有资源普通会员都能下载吗?
- 本站所有资源普通会员都可以下载,需要消耗金币下载的白金会员资源,通过每日签到,即可获取免费金币,金币可累积使用。