Heim >Web-Frontend >js-Tutorial >Was Sie über die Entwicklung mit JavaScript wissen müssen

Was Sie über die Entwicklung mit JavaScript wissen müssen

伊谢尔伦
伊谢尔伦Original
2016-11-22 11:38:41873Durchsuche

Eröffnungsübersicht

Die erfolgreiche Anwendung der Ajax-Technologie in Gmail und die Einführung der leistungsstarken V8-Engine haben das Schreiben von Webanwendungen populär gemacht. Anwendungen mit komplexen Interaktionen können auch mithilfe der Front-End-Technologie geschrieben werden. Im Vergleich zu nativen Anwendungen bieten Webanwendungen die folgenden Vorteile:

Plattformübergreifend, geringe Entwicklungs- und Wartungskosten

Bequem zu aktualisieren und zu veröffentlichen, es gibt kein Versionskonzept Veröffentlichung jederzeit und überall ohne Benutzerbewusstsein.

Responsive Design ermöglicht die plattformübergreifende Nutzung von Webanwendungen und derselbe Code passt sich an verschiedene Bildschirmgrößen an

Auch wenn die Webanwendung Wird die Lösung am Ende nicht genutzt, ist sie dennoch geeignet Prototypen entwickeln

Natürlich sind Webanwendungen nicht ohne Mängel. Da die Browser verschiedener Plattformen und Hersteller nicht genau gleich sind, fallen auch einige Kosten für die plattformübergreifende Kompatibilität an. Darüber hinaus ist die Leistung von Webanwendungen nicht so gut wie die von nativen Anwendungen und die Interaktion ist manchmal nicht sehr reibungslos. In Verbindung mit den Einschränkungen der HTML5-API ist die Verwendung von Webanwendungen für einige Funktionen nicht geeignet. Aus diesen Gründen sind Hybridlösungen beliebt geworden, die die Vorteile beider kombinieren (z. B. werden WeChat, mobiles QQ und mobile QQ-Browser einige Webseiten einbetten).

Basierend auf der Entwicklungserfahrung des Autors finden Sie hier eine Zusammenfassung einiger Probleme, die bei der Entwicklung von Webanwendungen auftreten müssen.

Modulare Programmierung

Modulare Programmierung ist eine wesentliche Funktion zum Schreiben umfangreicher Anwendungen. Im Vergleich zu anderen gängigen Programmiersprachen bietet Javascript keine direkte Unterstützung für Module, geschweige denn die Aufrechterhaltung von Abhängigkeiten zwischen Modulen Die Pflege des Javascript-Codes ist äußerst schwierig und die Reihenfolge des in den 3f1c4e4b6b16bbbd69b2ee476dc4f83a-Tags enthaltenen Codes erfordert eine manuelle Pflege.

Um die modulare Programmierung zu unterstützen, müssen zwei Probleme gelöst werden:

unterstützt das Schreiben und Benennen von Modulen, um Namenskonflikte und die Verwendung globaler Variablen zu verhindern;

unterstützt die Anzeige bestimmter Modulabhängigkeiten und lädt abhängige Module automatisch, wenn das Programm ausgeführt wird.

Das von Douglas Crockford im Buch „Javascript: The Good Parts“ vorgeschlagene Modulmuster nutzt die Abschlusstechnologie von Javascript, um das Konzept von Modulen zu simulieren und Namenskonflikte sowie die Verwendung globaler Variablen zu verhindern. Damit ist das erste Problem gelöst.

var moduleName = function () {
    // Define private variables and functions
    var private = ...
    // Return public interface.
    return {
        foo: ...
    };
}();

Um das zweite Problem zu lösen, hat die CommonJS-Organisation die AMD-Spezifikation definiert, um Entwicklern die Anzeige von Abhängigkeiten zwischen bestimmten Modulen und lastabhängigen Modulen bei Bedarf zu erleichtern. RequireJS ist eine beliebte Implementierung der AMD-Spezifikation.

Zuerst definieren wir Modul A in a.js.

define(function () {
    return {
        color: "black",
        size: 10
    };
});

Dann definieren wir Modul B so, dass es von Modul A abhängt.

define(["a"], function (A) {
    // ...
});

RequireJS garantiert, wann Modul B ist ausgeführt Modul A wurde geladen. Spezifische Details finden Sie in der offiziellen Dokumentation von RequireJS.

Laden von Skripten

Der einfachste Weg, Skripte zu laden, besteht darin, sie in den 93f0f5c25f18dab9d176bd4f6de5d30e zu laden.

<head>
    <script src="base.js" type="text/javascript"></script>
    <script src="app.js" type="text/javascript"></script>
</head>

Der Nachteil ist:

Das Laden und Parsen wird zuerst synchron ausgeführt, dann analysiert und ausgeführt und dann wird app.js heruntergeladen 🎜>Beim Laden eines Skripts wird auch das Rendern von DOM-Elementen nach 3f1c4e4b6b16bbbd69b2ee476dc4f83a blockiert.

Um diese Probleme zu lindern, ist es mittlerweile üblich, 3f1c4e4b6b16bbbd69b2ee476dc4f83a am Ende von 6c04bd5ca3fcae76e30b72ad730ca86d zu platzieren.

Aber nicht alle Skripte können am Ende von 6c04bd5ca3fcae76e30b72ad730ca86d platziert werden. Beispielsweise muss beim Rendern der Seite eine gewisse Logik ausgeführt werden, für die meisten Skripte ist eine solche Anforderung jedoch nicht erforderlich.
  <script src="base.js" type="text/javascript"></script>
    <script src="app.js" type="text/javascript"></script>
</body>

Das Platzieren des Skripts am Ende von 6c04bd5ca3fcae76e30b72ad730ca86d löst immer noch nicht das Problem des sequentiellen Herunterladens. Einige Browserhersteller sind sich dieses Problems ebenfalls bewusst und beginnen, asynchrone Downloads zu unterstützen. HTML5 bietet auch eine Standardlösung:

Mit dem async-Attribut gekennzeichnete Skripte weisen darauf hin, dass Sie darin keinen Code wie document.write verwenden. Der Browser lädt diese Skripte asynchron herunter und führt sie aus und verhindert nicht das Rendern des DOM-Baums. Dies führt jedoch zu einem weiteren Problem: Aufgrund der asynchronen Ausführung wird app.js möglicherweise vor base.js ausgeführt, was zu Fehlern führt, wenn zwischen ihnen Abhängigkeiten bestehen.
<script src="base.js" type="text/javascript" async></script>
<script src="app.js" type="text/javascript" async></script>

Apropos, was wir aus Entwicklersicht tatsächlich brauchen, sind diese Funktionen:

Asynchrones Herunterladen, das Rendern des DOM nicht blockieren

Auflösen gemäß Modulabhängigkeiten ermitteln und das Skript ausführen.

Das Laden von Skripten muss also tatsächlich in Verbindung mit modularen Programmierproblemen gelöst werden. RequireJS zeichnet nicht nur die Abhängigkeiten zwischen Modulen auf, sondern bietet auch das Laden und Ausführen bei Bedarf basierend auf Abhängigkeiten (Einzelheiten finden Sie in der offiziellen Dokumentation von RequireJS).

Weitere Optionen zum Laden von Skripten finden Sie hier.

Bereitstellung statischer Ressourcendateien

Die statischen Ressourcendateien hier beziehen sich auf CSS, Javascript und einige von CSS benötigte Bilder dokumentieren. Bei ihrer Bereitstellung müssen zwei Aspekte berücksichtigt werden:

Download-Geschwindigkeit

Versionsverwaltung

Ein Merkmal statischer Ressourcendateien ist, dass sie sich selten ändern und nichts mit der Benutzeridentität zu tun haben (d. h. nichts mit Cookies zu tun haben), sodass sie sich sehr gut für die Zwischenspeicherung eignen. Sobald sich andererseits die statische Ressourcendatei ändert, muss der Browser die neueste Version vom Webserver herunterladen. Wenn eine neue Version einer Webanwendung veröffentlicht wird, werden nicht alle Benutzer die neue Version sofort verwenden. Die alte Version und die neue Version werden nebeneinander existieren, was Probleme mit der Versionsübereinstimmung mit sich bringt. Ältere Anwendungsversionen müssen ältere Versionen von CSS und Javascript herunterladen, und neuere Anwendungsversionen müssen neuere Versionen statischer Ressourcen herunterladen.

Um Versionsinkonsistenzen zu verhindern, müssen die statischen Ressourcendateien jedes Mal umbenannt werden, wenn eine neue Version der Anwendung veröffentlicht wird, sodass der alte HTML-Code auf die alten statischen Dateien verweist und der neue HTML-Code auf die neue statische Dateien. Ein gängiger Ansatz besteht darin, dem Dateinamen einen Zeitstempel hinzuzufügen.

Um freie Referenzen zu verhindern, sollten Ressourcendateien vor HTML veröffentlicht werden.

Die obige Lösung kann das Versionsproblem lösen, sodass die Cache-Zeit jeder statischen Datei beliebig groß eingestellt werden kann, um wiederholte Downloads zu verhindern. Gleichzeitig wird der Browser rechtzeitig aktualisiert, wenn a neue Version ist erschienen.

Um das Problem der Download-Geschwindigkeit zu lösen, können Sie die folgenden Lösungen in Betracht ziehen:

Führen Sie statische Dateien zusammen, um zu viele Dateien zu vermeiden. Für den Download sind normalerweise mehr Verbindungen erforderlich die Anzahl der Verbindungen zum gleichen Domainnamen;

Komprimieren Sie statische Dateien; CSS und Javascript enthalten normalerweise viele Leerzeilen, Einrückungen und Kommentare, die beim Veröffentlichen entfernt werden können; >Statische Dateien haben normalerweise nichts mit Cookies zu tun. Um die Übertragungsgröße zu reduzieren und die Cache-Trefferquote zu erhöhen (der zwischengespeicherte Schlüssel muss Cookies berücksichtigen), werden statische Dateien am besten auf einem Domainnamen ohne Cookies gehostet

Schließlich ist es auch am wichtigsten, den oben genannten Prozess zu automatisieren.

MVC-Programmiermodell

Webanwendungen verwenden ein ereignisgesteuertes Programmiermodell, das mit nativen Anwendungen identisch ist. Der einzige Unterschied besteht darin, dass die von der Infrastruktur bereitgestellte API unterschiedlich ist. Die UI-Programmierung übernimmt normalerweise das MVC-Entwurfsmuster. Am Beispiel des beliebten Backbone.js umfasst es die folgenden Teile:

Modell

Die einzige Datenquelle

Verantwortlich zum Abrufen und Speichern von Daten

Kann einen Caching-Mechanismus bereitstellen

Benachrichtigen Sie andere Objekte durch Ereignisse, wenn sich Daten ändern

Ansicht

ist für das Rendern verantwortlich

Hören Sie sich sowohl UI-Ereignisse als auch Modellereignisse der Zeichnungs-UI an

Das Rendering-Ergebnis hängt von zwei Datentypen ab: Modell- und UI-Interaktionsstatus

Der Interaktionsstatus der UI wird normalerweise in der Ansicht gespeichert Objekt, und manchmal wird es der Einfachheit halber auch im DOM-Baumknoten gespeichert

Um die Renderkosten zu senken, versuchen Sie, den Bereich zu reduzieren, der gerendert werden muss, und rendern Sie bei jeder Datenänderung nur den betroffenen Bereich

Router

ist für die Überwachung von URL-Änderungen und die Benachrichtigung des entsprechenden View-Objekts beim Rendern der Seite verantwortlich

Um MVC effektiv nutzen zu können, müssen mehrere Probleme bezahlt werden Aufmerksamkeit auf.

Das Modell sollte vollständig von der Ansicht isoliert sein.

Das Modell bietet nur Zugriff auf Daten und sollte sich nicht auf die Ansicht verlassen, sodass das Modell die Existenz der Ansicht nicht kennen sollte. Daher kann das Modell keinen Verweis auf ein View-Objekt enthalten. Wenn sich die Daten des Modells ändern, kann es die Ansicht nur über Ereignisse benachrichtigen

View verwendet Delegation, um UI-Ereignisse während der Initialisierung abzuhören

Hier gibt es zwei wichtige Punkte:

Während der Initialisierung Beim Lauschen auf Ereignisse var View = Backbone.View.extend({ initialize: function () { this.$el.on('click', '#id', function () { // … }); } } );

Mit Ausnahme einiger Sonderfälle (siehe unten) sollten alle UI-Ereignisse initialisiert werden, wenn die Ansicht initialisiert wird, um zu verhindern, dass dasselbe Ereignis mehrmals gebunden wird. Auch wenn einige Ereignisse dynamisch überwacht werden (manchmal ist eine Überwachung erforderlich, manchmal ist keine Überwachung erforderlich, z. B. sind einige Schaltflächen manchmal gültig und manchmal ungültig), müssen sie dennoch während der Initialisierung überwacht und dann in der Ereignisrückruffunktion beurteilt werden. Muss bearbeitet werden. Dadurch wird die Logik einfacher und leichter zu warten.

Verwenden Sie die Delegationsmethode, um UI-Ereignisse zu überwachen

Informationen zur Delegationsmethode finden Sie in der jQuery-Dokumentation.

Oben wurde betont, dass Ereignisse während der Initialisierung überwacht werden sollten. Aber das DOM, das während der Initialisierung überwacht werden muss Der Knoten existiert möglicherweise noch nicht, sodass das Ereignis nicht direkt gebunden werden kann und nur die Delegation verwendet werden kann. Allerdings setzt die Delegationsmethode voraus, dass Ereignisse sprudeln können.

Für Ereignisse, die nicht blasen können (z. B. das Ladeereignis von a1f02c36ba31691bcfe87b2722de723b), können sie nur direkt gebunden werden, wenn ihre Existenz garantiert ist, und nicht unbedingt während der Initialisierung.

Complex View ist in einer Baumhierarchie organisiert

Die Funktion ist zu groß und muss in mehrere Unterfunktionen aufgeteilt werden. Wenn die Logik der Ansicht zu komplex ist, sollte sie entsprechend der Seitenstruktur in mehrere Unteransichten aufgeteilt werden:

Die übergeordnete Ansicht greift per Referenz auf die Unteransicht zu, die Unteransicht sollte jedoch darauf zugreifen keinen Verweis auf die übergeordnete Ansicht enthalten;

Die untergeordnete Ansicht ist nur für die Darstellung ihres eigenen Bereichs verantwortlich, und die übergeordnete Ansicht ist für die Darstellung anderer Bereiche verantwortlich.

Die übergeordnete Ansicht greift darauf zu die Funktionen der untergeordneten Ansicht über Funktionsaufrufe und die untergeordnete Ansicht kommuniziert mit der übergeordneten Ansicht über Ereignisse

Unteransichten können nicht direkt miteinander kommunizieren.

Weitere Tipps finden Sie unter Backbone-Techniken und -Muster.

Offline-Anwendungscache

Um das Webanwendungserlebnis reibungsloser zu gestalten, können Sie die Verwendung des HTML5-Offline-Anwendungscache in Betracht ziehen. Es sind jedoch folgende Punkte zu beachten:

Verwechseln Sie das Offline-Anwendungs-Caching nicht mit dem HTTP-Caching-Mechanismus. Ersteres ist eine neue Funktion, die von HTML5 eingeführt wurde und unabhängig vom HTTP-Caching-Mechanismus existiert

Cache manifest文件不应被HTTP缓存太久(通过HTTP头Cache-Control控制缓存 时间),否则发布新版后浏览器不会及时监测到变化并下载新文件;

在Cache manifest文件的NETWORK节放一个*,否则没有列在这个文件的资源不 会被请求;

不适合缓存的请求最好都放在NETWORK节;

如果之前使用过离线应用缓存现在不想再使用了,从100db36a723c770d327fc0aef2ce13b1删除manifest属性, 并发送404响应给manifest文件请求。仅仅删除manifest属性是没有效的。

线上错误报告

Javascript是一个动态语言,许多检查都是在运行时执行的,所以大多数错误只有执行到的时候才能检查到,只能在发布前通过大量测试来发现。即使这样仍可能有少数 没有执行到的路径有错误,这只能通过线上错误报告来发现了。

window.onerror = function (errorMsg, fileLoc, linenumber) {
    var s = &#39;url: &#39; + document.URL + &#39;\nfile: &#39; + fileLoc
       + &#39;\nline number: &#39; + linenumber
       + &#39;\nmessage: &#39; + errorMsg;
    Log.error(s); // 发给服务器统计监控
    console.log(s);
};

通常线上的Javascript都是经过了合并和压缩的,上报的文件名和行号基本上没法对 应到源代码,对查错帮助不是很大。不过最新版的Chrome支持在onerror的回调函数 中获取出错时的栈轨迹:window.event.error.stack.


Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn