Maison  >  Article  >  interface Web  >  La manière la plus complète de créer des composants React

La manière la plus complète de créer des composants React

小云云
小云云original
2018-01-23 10:55:031550parcourir

J'aime beaucoup utiliser React car je pense que son plus grand avantage est qu'il est assez simple. Il y a une différence entre simple et facile, et je veux dire que React est facile aussi. Bien sûr, il faut un certain temps pour le comprendre. Une fois que vous maîtriserez son contenu principal, tout le reste se mettra en place. Les parties les plus difficiles seront couvertes ci-dessous.

Couplage & Cohésion

Ces indicateurs (couplage & cohésion) nous posent plus ou moins des défis pour changer nos habitudes de programmation. Ils sont souvent utilisés dans la programmation orientée objet basée sur les classes. Nous ferons également référence et appliquerons les mêmes règles lors de l'écriture des composants React.

Le couplage fait référence aux interconnexions et aux dépendances entre les éléments. Si vous modifiez un élément et devez mettre à jour un autre élément de manière synchrone, nous appelons cela un couplage étroit. Un couplage lâche signifie que lorsqu'un élément est modifié, un autre élément n'a pas besoin d'être modifié. Par exemple, affichez la fonction de montant du virement bancaire. Si le montant affiché repose sur des calculs de taux de change, le code affiché sera mis à jour lorsque la structure de conversion interne changera. Si nous concevons un système faiblement couplé basé sur une interface d'élément, les modifications apportées à l'élément n'affecteront pas l'affichage de la couche de vue. Il est évident que les composants faiblement couplés sont plus faciles à gérer et à contrôler.

La cohésion consiste à savoir si un composant n'est responsable que d'une seule chose. Cet indicateur suit le principe unique et le principe Unix : se concentrer sur une chose et bien le faire. Si l'affichage formaté des soldes des comptes nécessite de calculer les taux de change pertinents et de vérifier si l'autorisation d'afficher l'historique est disponible, cela implique de nombreuses responsabilités fonctionnelles et ces fonctions ne dépendent pas les unes des autres. Peut-être que la gestion des autorisations et les taux de change devraient être des composants différents. D'un autre côté, s'il y a plusieurs composants, un pour la partie entière, un pour la partie décimale et un pour l'affichage de la monnaie, et que le programmeur souhaite afficher la balance, il doit trouver tous les composants à assembler. Le défi est de créer des composants hautement cohérents.

Construire des composants

Il existe de nombreuses façons de créer des composants. Nous voulons que les composants soient réutilisables dans une mesure raisonnable. Nous souhaitons également créer de petits composants pouvant être utilisés dans des composants plus grands. Idéalement, nous souhaitons créer des composants faiblement couplés et hautement agrégés afin que notre système soit plus facile à gérer et à faire évoluer. Les accessoires des composants React sont similaires aux paramètres des fonctions et peuvent également être considérés comme des composants dotés de fonctions sans état. Nous devons réfléchir à la manière dont les accessoires sont définis dans les composants et à la manière dont les composants peuvent être réutilisés.

Ensuite, nous utilisons le système de gestion des dépenses comme arrière-plan, analysons le format détaillé des dépenses et présentons comment créer des composants :

type Expense {
      description: string
      category: string
      amount: number
      doneAt: moment
    }

Selon le modèle, il y aura les éléments suivants Plusieurs façons de modéliser par programmation les formats de dépenses :

  • Aucun accessoire

  • Passer un objet de dépense

  • Passer les attributs nécessaires

  • Passer une carte de tous les attributs

  • Passer un sous-objet formaté

Les avantages et les inconvénients de l'utilisation des méthodes de transfert ci-dessus sont discutés ci-dessous. Cependant, vous devez toujours faire attention à l'utilisation de l'une des méthodes ci-dessus en fonction du scénario d'utilisation et des systèmes dépendants. C’est aussi ce que nous faisons : construire des scènes abstraites appropriées.

Aucun accessoire

C'est la solution la plus simple, qui consiste souvent à créer un composant qui écrit des données statiques.

const ExpenseDetails = () => (
      <p className=&#39;expense-details&#39;>
         <p>Category: <span>Food</span></p>
         <p>Description: <span>Lunch</span></p>
         <p>Amount: <span>10.15</span></p>
         <p>Date: <span>2017-10-12</span></p>
      </p>
    )

Sans passer d'accessoires, cela ne nous donnera aucune flexibilité, et le composant ne peut être utilisé que dans un seul scénario. Dans l'exemple de détail des dépenses, nous pouvons voir qu'au départ, le composant doit accepter certains accessoires. Cependant, dans certains scénarios, ne pas avoir d’accessoires est également une bonne solution. Premièrement, nous pouvons utiliser certains composants dont les accessoires contiennent du contenu qui ne peut pas être facilement modifié, comme des marques, des logos ou des informations sur l'entreprise.

const Logo = () => (
      <p className=&#39;logo&#39;>
       <img src=&#39;/logo.png&#39; alt=&#39;DayOne logo&#39;/>
      </p>
    )

Écrire des composants aussi petits que possible rend le système plus facile à maintenir. Conservez les informations au même endroit et n'avez besoin de les modifier qu'à un seul endroit. N'écrivez pas de code en double à plusieurs endroits.

Transmettre l'objet de dépense

Lorsque les détails de la dépense sont déterminés, nous devons transmettre les données au composant. Tout d’abord, nous devons transmettre un objet de dépense.

const ExpenseDetails = ({ expense }) => (
      <p className=&#39;expense-details&#39;>
         <p>Category: <span>{expense.category}</span></p>
         <p>Description: <span>{expense.description}</span></p>
         <p>Amount: <span>{expense.amount}</span></p>
         <p>Date: <span>{expense.doneAt}</span></p>
      </p>
    )

Il est logique de transmettre l'objet de dépense au composant détails de la dépense. Le format des détails des dépenses est très cohérent et affiche les données de dépenses. Chaque fois que vous devez changer le format, c'est le seul endroit où vous pouvez le modifier. Changer le format des détails de la dépense n'aura aucun effet secondaire sur l'objet de dépense lui-même.

Ce composant est étroitement couplé à l'objet de dépense. Est-ce une mauvaise chose ? Bien sûr que non, mais nous devons être conscients de la manière dont cela affecte nos systèmes. En passant un objet comme accessoire, le composant détails des dépenses s'appuiera sur la structure interne des dépenses. Lorsque nous modifions la structure interne des dépenses, nous devrons modifier le composant des détails des dépenses. Bien entendu, il suffit de le modifier à un seul endroit.

Comment cette conception s'adapte-t-elle aux changements futurs ? Si nous ajoutons, modifions ou supprimons un champ, nous n'aurons à modifier qu'un seul composant. Et si nous devions ajouter un autre format d'affichage de calendrier ? Nous pouvons ajouter un nouvel accessoire pour le formatage du calendrier.

const ExpenseDetails = ({ expense, dateFormat }) => (
      <p className=&#39;expense-details&#39;>
         <p>Category: <span>{expense.category}</span></p>
         <p>Description: <span>{expense.description}</span></p>
         <p>Amount: <span>{expense.amount}</span></p>
         <p>Date: <span>{expense.doneAt.format(dateFormat)}</span></p>
      </p>
    )

我们开始增加属性来使组件更加灵活。如果只有几个选项,那么一切都是很ok的。系统业务开始扩展后问题就来了,在不同的场景下我们需要维护大量的props。

const ExpenseDetails = ({ expense, dateFormat, withCurrency, currencyFormat, isOverdue, isPaid ... })

 

增加props可以使得组件重用性更好,但你可能设计了多重功能职责的组件。这种规则也同样在函数写法中运用。可以用多个参数来创建一个函数,当参数的数目超过3个或者4个时候,意味着这个函数在做很多事情了,也许这时候应该将函数拆成更小的函数来的更加简单。

随着组件props的增加,我们将其拆分成定义明确的组件,比如:OverdueExpenseDetails, PaidExpenseDetails等。

只传递必要的属性

为了减少对象自身的内容,我们可以只传递必要的属性值。

const ExpenseDetails = ({ category, description, amount, date }) => (
      <p className=&#39;expense-details&#39;>
         <p>Category: <span>{category}</span></p>
         <p>Description: <span>{description}</span></p>
         <p>Amount: <span>{amount}</span></p>
         <p>Date: <span>{date}</span></p>
      </p>
    )

 

我们分别传递属性,这样我们将一部分工作责任转移给了组件使用者。如果费用的内部结构发生变化,他将不会影响费用明细的格式化。但可能影响每个使用组件的地方,因为我们可能需要修改props。当我们以独立的属性传递props时候,一个组件将更加抽象了。

只传递需要的字段对未来设计改动是如何影响的?增加、更新或者删除字段将不会很容易。无论何时我们要增加一个字段,我们不仅仅要改变费用细节的实现,也需要改变每个使用组件的地方。另外一个方面,支持多种日历格式化几乎是现成的,我们可以传递日历作为prop,也可以传递格式化后的日历。

<ExpenseDetails 
      category={expense.category} 
      description={expense.description}
      amount={expense.amount}
      date={expense.doneAt.format(&#39;YYYY-MM-DD&#39;)}
    />

 

决定如何展示特定的字段应该在掌握在具体使用组件的人手中,这将不是费用明细组件关心的内容。

传递map或者array的属性

为了达到组件抽象化,我们可以传递一个map的属性值。

const ExpenseDetails = ({ expense }) => (
      <p class=&#39;expense-details&#39;>
      {
        _.reduce(expense, (acc, value, key) => {
          acc.push(<p>{key}<span>{value}</span></p>)
        }, [])
      }
      </p>
    )

 

使用组件的人控制费用明细的格式化,传递给组件的对象格式则必须正确。

const expense = {
      "Category": "Food",
      "Description": "Lunch",
      "Amount": 10.15,
      "Date": 2017-10-12
    }

 

这个方案有很多缺陷,我们很难控制组件展示的样式,并且展示顺序也没有指定。因此,如果我们需要某种顺序的话,可以采用array代替map来解决这个问题。但是仍然还有缺陷。

传递map 和array作为props 不与费用耦合,也根本与它不一致。增加和删除新属性虽然只改变了prop,但是我们无法控制组件本身的格式。如果我们只改变类别的格式化,这不是一个可行的办法。(确切地说,总有一个办法来解决,例如,传递另外一个格式化后的props。这个解决方案似乎不再简单了。)

传递一个格式化的子对象

我们也可以只通过直接传对一个子对象,这样就能考虑更少的组件内需要如何展示。

const ExpenseDetails = ({ children }) => (
      <p class=&#39;expense-details&#39;>
        { children }
      </p>
    )

 

在这种情况下,费用明细只是一个提供结构和样式的容器。展示所有信息则是使用组件的人必须提供的。

<ExpenseDetails>
      <p>Category: <span>{expense.category}</span></p>
      <p>Description: <span>{expense.description}</span></p>
      <p>Amount: <span>{expense.amount}</span></p>
      <p>Date: <span>{expense.doneAt}</span></p>
    </ExpenseDetails>

 

在费用明细这个案例中,我们需要重复许多工作,因此这也许不是一个好的解决方案。尽管如此,灵活性则是巨大的,因为有可能有很多不同的格式化操作。增删改只需要改变使用组件时候传入的值。日期格式也是一样的,我们虽然失去了功能内聚的特点,但这也是我们不得不付出的代价。

环境为王

正如你所看到,我们讨论了它们的不同优缺点和可能性。哪一个最好呢,这取决于:

  • 项目本身

  • 项目阶段

  • 组件自身,需要很多特殊的组件组成还是只需要简单的一些选项值

  • 自己的习惯

  • 使用环境-适合频繁的改变和被多次使用

没有一个万能的解决方案,一个方案也并不能适用所有场景。我们如何构建组件对于系统的维护和系统可扩展方面有着深远的影响。这完全依赖于组件所使用的环境。非常幸运的是,我们有很多可使用的方案。组件是功能的抽象集合,它既能构建小系统也能构建大系统。所以这仅仅只是一个选择问题。

相关推荐:

store优化React组件的方法详解

如何在React组件“外”使用父组件的Props

React组件的生命周期函数是什么

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn