Ich verwende React sehr gerne, weil der größte Vorteil meiner Meinung nach darin besteht, dass es einfach genug ist. Es gibt einen Unterschied zwischen einfach und leicht, und ich meine, React ist auch einfach. Natürlich braucht es einige Zeit, um es zu verstehen. Sobald Sie den Kerninhalt beherrschen, wird sich alles andere von selbst ergeben. Die schwierigeren Teile werden weiter unten behandelt.
Diese Indikatoren (Kopplung und Kohäsion) stellen uns mehr oder weniger vor Herausforderungen bei der Änderung unserer Programmiergewohnheiten. Sie werden häufig in der klassenbasierten objektorientierten Programmierung verwendet. Wir werden uns auch beim Schreiben von React-Komponenten auf dieselben Regeln beziehen und diese anwenden.
Kopplung bezieht sich auf die Verbindungen und Abhängigkeiten zwischen Elementen. Wenn Sie ein Element ändern und ein anderes Element synchron aktualisieren müssen, nennen wir dies enge Kopplung. Lose Kopplung bedeutet, dass beim Ändern eines Elements kein anderes Element geändert werden muss. Zeigen Sie beispielsweise die Funktion „Überweisungsbetrag“ an. Wenn der angezeigte Betrag auf Wechselkursberechnungen beruht, wird der angezeigte Code aktualisiert, wenn sich die interne Umrechnungsstruktur ändert. Wenn wir ein lose gekoppeltes System basierend auf einer Elementschnittstelle entwerfen, haben Änderungen am Element keinen Einfluss auf die Anzeige der Ansichtsebene. Offensichtlich sind lose gekoppelte Komponenten einfacher zu verwalten und zu kontrollieren.
Zusammenhalt ist, ob eine Komponente nur für eine Sache verantwortlich ist. Dieser Indikator folgt dem Single-Prinzip und dem Unix-Prinzip: Konzentrieren Sie sich auf eine Sache und machen Sie sie gut. Wenn die formatierte Anzeige von Kontoständen die Berechnung relevanter Wechselkurse und die Prüfung, ob die Berechtigung zur Einsicht in die Historie vorhanden ist, erfordert, dann beinhaltet dies viele funktionale Verantwortlichkeiten, und diese Funktionen sind nicht voneinander abhängig. Möglicherweise sollten Berechtigungsverwaltung und Wechselkurse unterschiedliche Komponenten sein. Wenn andererseits mehrere Komponenten vorhanden sind, eine für den ganzzahligen Teil, eine für den Dezimalteil und eine für die Währungsanzeige, und der Programmierer den Kontostand anzeigen möchte, muss er alle Komponenten zum Zusammenbauen finden. Die Herausforderung besteht darin, hochkohäsive Komponenten zu schaffen.
Es gibt viele Möglichkeiten, Bauteile zu erstellen. Wir wollen, dass Komponenten in einem angemessenen Umfang wiederverwendbar sind. Wir wollen auch kleine Komponenten bauen, die in größeren Komponenten verwendet werden können. Idealerweise möchten wir lose gekoppelte und stark aggregierte Komponenten aufbauen, damit unser System einfacher zu verwalten und zu skalieren ist. Requisiten in React-Komponenten ähneln Parametern in Funktionen und können auch als Komponenten mit zustandslosen Funktionen betrachtet werden. Wir müssen darüber nachdenken, wie Requisiten in Komponenten definiert werden und wie Komponenten wiederverwendet werden können.
Als nächstes verwenden wir das Ausgabenverwaltungssystem als Hintergrund, analysieren das detaillierte Ausgabenformat und stellen vor, wie Komponenten erstellt werden:
type Expense { description: string category: string amount: number doneAt: moment }
Gemäß dem Modell gibt es die folgenden Mehrere Möglichkeiten, Ausgabenformate programmgesteuert zu modellieren:
Keine Requisiten
Ein Ausgabenobjekt übergeben
Übergeben Sie die erforderlichen Attribute
Übergeben Sie eine Karte aller Attribute
Übergeben Sie ein formatiertes Unterobjekt
Die Vor- und Nachteile der Verwendung der oben genannten Übertragungsmethoden werden im Folgenden erläutert. Sie müssen jedoch immer auf die Verwendung einer der oben genannten Methoden achten, abhängig vom Nutzungsszenario und den abhängigen Systemen. Das ist es auch, was wir tun, entsprechend abstrakte Szenen zu bauen.
Dies ist die einfachste Lösung, die oft darin besteht, eine Komponente zu erstellen, die statische Daten schreibt.
const ExpenseDetails = () => ( <p className='expense-details'> <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> )
Ohne die Weitergabe von Requisiten erhalten wir keine Flexibilität und die Komponente kann nur in einem einzigen Szenario verwendet werden. Im Kostendetailbeispiel können wir sehen, dass die Komponente zunächst einige Requisiten akzeptieren muss. In manchen Szenarien ist es jedoch auch eine gute Lösung, auf Requisiten zu verzichten. Erstens können wir einige Komponenten verwenden, deren Requisiten Inhalte enthalten, die nicht einfach geändert werden können, z. B. Marken, Logos oder Unternehmensinformationen.
const Logo = () => ( <p className='logo'> <img src='/logo.png' alt='DayOne logo'/> </p> )
Das Schreiben von Komponenten so klein wie möglich macht die Wartung des Systems einfacher. Behalten Sie Informationen an einem Ort und müssen Sie sie nur an einem Ort ändern. Schreiben Sie keinen doppelten Code an mehreren Stellen.
Wenn die Ausgabendetails ermittelt sind, müssen wir Daten an die Komponente übergeben. Zuerst müssen wir ein Ausgabenobjekt übergeben.
const ExpenseDetails = ({ expense }) => ( <p className='expense-details'> <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> )
Es ist sinnvoll, das Spesenobjekt an die Spesendetailskomponente zu übergeben. Das Format der Spesendetails ist äußerst konsistent und zeigt Spesendaten an. Wann immer Sie das Format ändern müssen, ist dies der einzige Ort, an dem Sie es ändern können. Das Ändern des Formats der Spesendetails hat keine Nebenwirkungen auf das Spesenobjekt selbst.
Diese Komponente ist eng mit dem Kostenobjekt verknüpft. Ist das eine schlechte Sache? Natürlich nicht, aber wir müssen uns darüber im Klaren sein, welche Auswirkungen dies auf unsere Systeme hat. Wenn ein Objekt als Requisiten übergeben wird, stützt sich die Spesendetailskomponente auf die interne Spesenstruktur. Wenn wir die interne Struktur der Ausgaben ändern, müssen wir auch die Komponente mit den Ausgabendetails ändern. Natürlich müssen wir es nur an einer Stelle ändern.
Wie passt sich dieses Design an zukünftige Änderungen an? Wenn wir ein Feld hinzufügen, ändern oder löschen, müssen wir nur eine Komponente ändern. Was ist, wenn wir eine weitere formatierte Kalenderanzeige hinzufügen müssen? Wir können eine neue Requisite für die Kalenderformatierung hinzufügen.
const ExpenseDetails = ({ expense, dateFormat }) => ( <p className='expense-details'> <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='expense-details'> <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('YYYY-MM-DD')} />
决定如何展示特定的字段应该在掌握在具体使用组件的人手中,这将不是费用明细组件关心的内容。
为了达到组件抽象化,我们可以传递一个map的属性值。
const ExpenseDetails = ({ expense }) => ( <p class='expense-details'> { _.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='expense-details'> { 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>
在费用明细这个案例中,我们需要重复许多工作,因此这也许不是一个好的解决方案。尽管如此,灵活性则是巨大的,因为有可能有很多不同的格式化操作。增删改只需要改变使用组件时候传入的值。日期格式也是一样的,我们虽然失去了功能内聚的特点,但这也是我们不得不付出的代价。
正如你所看到,我们讨论了它们的不同优缺点和可能性。哪一个最好呢,这取决于:
项目本身
项目阶段
组件自身,需要很多特殊的组件组成还是只需要简单的一些选项值
自己的习惯
使用环境-适合频繁的改变和被多次使用
没有一个万能的解决方案,一个方案也并不能适用所有场景。我们如何构建组件对于系统的维护和系统可扩展方面有着深远的影响。这完全依赖于组件所使用的环境。非常幸运的是,我们有很多可使用的方案。组件是功能的抽象集合,它既能构建小系统也能构建大系统。所以这仅仅只是一个选择问题。
相关推荐:
Das obige ist der detaillierte Inhalt vonDie umfassendste Möglichkeit, React-Komponenten zu erstellen. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!