Heim >Web-Frontend >js-Tutorial >Das Entwerfen eines JavaScript-Plug-In-Systems ist äußerst wichtig
【Verwandte Lernempfehlungen: Javascript-Video-Tutorial】
WordPress hat Plug-Ins, jQuery hat Plug-Ins, das Gleiche gilt für Gatsby, Eleventy und Vue.
Plugins sind ein häufiges Merkmal von Bibliotheken und Frameworks, und das aus gutem Grund: Sie ermöglichen Entwicklern, Funktionen auf sichere und erweiterbare Weise hinzuzufügen. Dies macht das Kernprojekt wertvoller und baut eine Community auf – und das alles ohne zusätzlichen Wartungsaufwand. Sehr gut!
Wie baut man also ein Stecksystem auf? Lassen Sie uns unser eigenes Plugin in JavaScript erstellen, um diese Frage zu beantworten.
Beginnen wir mit einem Beispielprojekt namens BetaCalc. BetaCalc soll ein minimalistischer JavaScript-Rechner sein, dem andere Entwickler „Schaltflächen“ hinzufügen können. Hier ist ein grundlegender Code für den Einstieg:
// 计算器const betaCalc = { currentValue: 0, setValue(newValue) { this.currentValue = newValue; console.log(this.currentValue); }, plus(addend) { this.setValue(this.currentValue + addend); }, minus(subtrahend) { this.setValue(this.currentValue - subtrahend); } };// 使用计算器betaCalc.setValue(3); // => 3betaCalc.plus(3); // => 6betaCalc.minus(2); // => 4复制代码
Um die Dinge einfach zu halten, definieren wir einen Taschenrechner als eine objektive Sache. Ein Taschenrechner funktioniert, indem er die Ergebnisse in console.log
ausgibt. console.log
打印结果来工作。
目前功能确实很有限。我们有一个 setValue
方法,该方法接受一个数字并将其显示在“屏幕”上。我们还有加法(plus
)和减法(minus
)方法,它们将对当前显示的值执行一个运算。
现在该添加更多功能了。首先创建一个插件系统。
我们将从创建一个注册(register
)方法开始,其他开发人员可以使用该方法向BetaCalc注册插件。该方法的工作很简单:获取外部插件,获取其 exec
函数,并将其作为新方法附加到我们的计算器上:
// 计算器const betaCalc = { // ...其他计算器代码在这里 register(plugin) { const { name, exec } = plugin; this[name] = exec; } };复制代码
这是一个示例插件,为我们的计算器提供了一个“平方(squared
)”按钮:
// 定义插件const squaredPlugin = { name: 'squared', exec: function() { this.setValue(this.currentValue * this.currentValue) } };// 注册插件betaCalc.register(squaredPlugin);复制代码
在许多插件系统中,插件通常分为两个部分:
在我们的插件中,exec
函数包含我们的代码,name
是我们的元数据。注册插件后,exec
函数将作为一种方法直接附加到我们的 betaCalc
对象,从而可以访问BetaCalc的 this
。
现在,BetaCalc有一个新的“平方”按钮,可以直接调用:
betaCalc.setValue(3); // => 3betaCalc.plus(2); // => 5betaCalc.squared(); // => 25betaCalc.squared(); // => 625复制代码
这个系统有很多优点。该插件是一种简单的对象字面量,可以传递给我们的函数。这意味着插件可以通过npm下载并作为ES6模块导入。易于分发是超级重要的!
但是我们的系统有一些缺陷。
通过为插件提供访问BetaCalc的 this
权限,他们可以对所有BetaCalc的代码进行读/写访问。虽然这对于获取和设置 currentValue
很有用,但也很危险。如果插件要重新定义内部函数(如 setValue
),则它可能会为BetaCalc和其他插件产生意外的结果。这违反了开放-封闭原则,即一个软件实体应该是开放的扩展,但封闭修改。
另外,“squared”函数通过产生副作用发挥作用。这在JavaScript中并不少见,但感觉并不好——特别是当其他插件可能处在同一内部状态的情况下。一种更实用的方法将大大有助于使我们的系统更安全、更可预测。
让我们再来看看一个更好的插件架构。下一个例子同时改变了计算器和它的插件API:
// 计算器const betaCalc = { currentValue: 0, setValue(value) { this.currentValue = value; console.log(this.currentValue); }, core: { 'plus': (currentVal, addend) => currentVal + addend, 'minus': (currentVal, subtrahend) => currentVal - subtrahend }, plugins: {}, press(buttonName, newVal) { const func = this.core[buttonName] || this.plugins[buttonName]; this.setValue(func(this.currentValue, newVal)); }, register(plugin) { const { name, exec } = plugin; this.plugins[name] = exec; } }; // 我们得插件,平方插件const squaredPlugin = { name: 'squared', exec: function(currentValue) { return currentValue * currentValue; } }; betaCalc.register(squaredPlugin);// 使用计算器betaCalc.setValue(3); // => 3betaCalc.press('plus', 2); // => 5betaCalc.press('squared'); // => 25betaCalc.press('squared'); // => 625复制代码
我们在这里做了一些值得注意的更改。
首先,我们将插件与“核心(core)”计算器方法(如plus和minus)分开,方法是将其放入自己的插件对象中。将我们的插件存储在plugins
对象中可使我们的系统更安全。现在,访问此plugins的插件将看不到BetaCalc属性,而只能看到 betaCalc.plugins
的属性。
其次,我们实现了一个 press
方法,该方法按名称查找按钮的功能,然后调用它。现在,当我们调用插件的 exec
函数时,我们将当前的计算器值(currentValue
)传递给该函数,并期望它返回新的计算器值。
本质上,这个新的 press
setValue
-Methode, die eine Zahl akzeptiert und auf dem „Bildschirm“ anzeigt. Wir haben auch Additions- (plus
) und Subtraktionsmethoden (minus
), die eine Operation mit dem aktuell angezeigten Wert durchführen. 🎜🎜Jetzt ist es an der Zeit, weitere Funktionen hinzuzufügen. Erstellen Sie zunächst ein Plugin-System. 🎜register
), mit der sich andere Entwickler beim BetaCalc-Plugin registrieren können . Was diese Methode macht, ist einfach: Holen Sie sich das externe Plugin, holen Sie sich seine Funktion exec
und hängen Sie es als neue Methode an unseren Rechner an: 🎜rrreee🎜Hier ist ein Beispiel-Plugin für unsere Berechnung. Der Browser stellt ein „ quadriert (quadrat
)“-Button: 🎜rrreee🎜In vielen Plug-In-Systemen sind Plug-Ins normalerweise in zwei Teile unterteilt: 🎜exec
unseren Code, name sind unsere Metadaten. Nach der Registrierung des Plugins wird die Funktion <code>exec
als Methode direkt an unser Objekt betaCalc
angehängt und ermöglicht den Zugriff auf this
von BetaCalc. 🎜🎜BetaCalc hat jetzt einen neuen „quadratischen“ Button, der direkt aufgerufen werden kann: 🎜rrreee🎜Dieses System hat viele Vorteile. Das Plugin ist ein einfaches Objektliteral, das an unsere Funktionen übergeben werden kann. Das bedeutet, dass Plugins über npm heruntergeladen und als ES6-Module importiert werden können. Eine einfache Verteilung ist super wichtig! 🎜🎜Aber unser System hat einige Mängel. 🎜🎜Indem Sie Plugins Zugriff auf die this
-Berechtigungen von BetaCalc gewähren, können sie Lese-/Schreibzugriff auf den gesamten BetaCalc-Code haben. Dies ist zwar nützlich, um currentValue
abzurufen und festzulegen, kann aber auch gefährlich sein. Wenn ein Plugin interne Funktionen (z. B. setValue
) neu definieren würde, könnte dies zu unerwarteten Ergebnissen für BetaCalc und andere Plugins führen. Dies verstößt gegen das Open-Closed-Prinzip, das besagt, dass eine Softwareeinheit offen für Erweiterungen, aber geschlossen für Änderungen sein sollte. 🎜🎜Außerdem erzeugt die Funktion „Quadrat“ Nebenwirkungen. Dies ist in JavaScript nicht ungewöhnlich, fühlt sich aber nicht gut an – insbesondere, wenn sich andere Plugins möglicherweise im gleichen internen Zustand befinden. Ein praktischerer Ansatz würde einen großen Beitrag dazu leisten, unsere Systeme sicherer und vorhersehbarer zu machen. 🎜plugins
-Objekten macht unser System sicherer. Nun sehen Plugins, die auf dieses Plugin zugreifen, nicht die BetaCalc-Eigenschaften, sondern nur die Eigenschaften von betaCalc.plugins
. 🎜🎜Zweitens haben wir eine press
-Methode implementiert, die die Funktion der Schaltfläche anhand des Namens sucht und sie dann aufruft. Wenn wir nun die Funktion exec
des Plugins aufrufen, übergeben wir den aktuellen Rechnerwert (currentValue
) an die Funktion und erwarten, dass sie den neuen Rechnerwert zurückgibt. 🎜🎜Im Wesentlichen wandelt diese neue press
-Methode alle unsere Taschenrechnertasten in reine Funktionen um. Sie nehmen einen Wert an, führen eine Operation aus und geben das Ergebnis zurück. Das hat viele Vorteile: 🎜Diese neue Architektur ist eingeschränkter als das erste Beispiel, funktioniert aber gut. Grundsätzlich setzen wir für Plugin-Autoren Leitplanken ein, die sie darauf beschränken, nur die Änderungen vorzunehmen, die wir von ihnen erwarten.
Eigentlich könnte es zu streng sein! Derzeit funktioniert unser Rechner-Plugin nur auf currentValue
. Wenn ein Plugin-Autor erweiterte Funktionen hinzufügen möchte (z. B. eine „Merken“-Schaltfläche oder eine Möglichkeit, den Verlauf zu verfolgen), kann er nicht viel tun.
Vielleicht ist das gut. Die Macht, die Sie Plugin-Autoren geben, ist ein empfindliches Gleichgewicht. Wenn Sie ihnen zu viel Leistung geben, kann dies die Stabilität Ihres Projekts beeinträchtigen. Wenn Sie ihnen aber zu wenig Energie geben, wird es für sie schwierig, ihre eigenen Probleme zu lösen – in diesem Fall sollten Sie besser darauf verzichten.
Wir haben noch viel zu tun, um unser System zu verbessern.
Wir können eine Fehlerbehandlung hinzufügen, um den Plugin-Autor zu benachrichtigen, wenn er vergisst, einen Namen oder Rückgabewert zu definieren. Es ist gut, wie ein QA-Entwickler zu denken und sich vorzustellen, wie unsere Systeme kaputt gehen könnten, damit wir diese Situationen proaktiv bewältigen können.
Wir können die Funktionalität des Plugins erweitern. Derzeit kann ein BetaCalc-Plugin eine Schaltfläche hinzufügen. Aber was wäre, wenn es auch Rückrufe für bestimmte Lebenszyklusereignisse registrieren könnte (z. B. wenn der Rechner gerade einen Wert anzeigt)? Oder was wäre, wenn es einen speziellen Ort gäbe, an dem ein Zustand über mehrere Interaktionen hinweg gespeichert werden könnte? Wird dies einige neue Anwendungsfälle eröffnen?
Wir können auch die Funktion der Plug-in-Registrierung erweitern. Was wäre, wenn ein Plugin bei einer Ersteinrichtung registriert werden könnte? Wird das Plugin dadurch flexibler? Was wäre, wenn ein Plugin-Autor eine ganze Reihe von Schaltflächen anstelle einer einzelnen Schaltfläche registrieren möchte – wie „BetaCalc Stats Package“? Welche Änderungen müssen vorgenommen werden, um dies zu unterstützen?
BetaCalc und sein Plug-in-System sind sehr einfach. Wenn Ihr Projekt größer ist, sollten Sie einige andere Plugin-Architekturen erkunden.
Ein guter Ausgangspunkt ist es, sich bestehende Projekte nach Beispielen erfolgreicher Plugin-Systeme anzusehen. Für JavaScript könnte dies jQuery, Gatsby, D3, CKEditor oder andere bedeuten. Möglicherweise möchten Sie sich auch mit den verschiedenen JavaScript-Entwurfsmustern vertraut machen, die jeweils unterschiedliche Schnittstellen und Kopplungsgrade bieten und Ihnen viele gute Möglichkeiten für die Plugin-Architektur bieten. Wenn Sie diese Optionen verstehen, können Sie die Bedürfnisse aller Nutzer Ihres Projekts besser berücksichtigen.
Zusätzlich zum Muster selbst gibt es viele gute Prinzipien der Softwareentwicklung, auf die Sie zurückgreifen können, um solche Entscheidungen zu treffen. Ich habe bereits einige Ansätze erwähnt (wie das Offen-Geschlossen-Prinzip und die lose Kopplung), aber einige andere verwandte Ansätze umfassen das Demeter-Gesetz und die Abhängigkeitsinjektion.
Ich weiß, es hört sich nach viel an, aber Sie müssen Ihre Recherche durchführen. Es gibt nichts Schmerzhafteres, als wenn jeder sein Plugin neu schreiben muss, weil man die Plugin-Architektur ändern muss. Dies ist eine schnelle Möglichkeit, das Vertrauen zu verlieren und dazu zu führen, dass die Menschen das Vertrauen in ihre zukünftigen Beiträge verlieren.
Eine gute Plugin-Architektur von Grund auf zu schreiben ist schwer! Sie müssen viele Überlegungen abwägen, um ein System aufzubauen, das den Bedürfnissen aller gerecht wird. Ist es einfach genug? Kann die Funktion mächtig sein? Wird es langfristig funktionieren?
Aber es lohnt sich, ein gutes Plug-in-System hilft allen und Entwickler können ihre Probleme frei lösen. Es gibt eine Vielzahl optionaler Funktionen, aus denen Endbenutzer wählen können. Sie können rund um Ihr Projekt ein Ökosystem und eine Community aufbauen. Es ist eine Win-Win-Situation.
Das obige ist der detaillierte Inhalt vonDas Entwerfen eines JavaScript-Plug-In-Systems ist äußerst wichtig. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!