Vorwort
Ich habe in letzter Zeit mit Angularjs gespielt. Ich muss sagen, dass das MVVM-Framework von Angularjs überall im Internet verfügbar ist die tatsächlich in Projekten verwendet werden Sie werden von Zeit zu Zeit auf verschiedene Fallstricke stoßen.
1. ng-repeat
ng-repeat wird verwendet, um zu identifizieren, dass ein Element wiederholt ausgegeben werden muss und der Inhalt der wiederholten Ausgabe eindeutig sein muss
<div ng-app="app" ng-controller="control"> <h3 ng-repeat="content in repeatContent">ng-repeat: {{ content }}</h3> </div>
let app = angular.module("app", []); app.controller("control", ($scope) => { // 输出李滨泓 $scope.repeatContent = ["李", "滨", "泓"]; // 下面存在两个“泓”,会报错 // $scope.repeatContent = ["李", "滨", "泓", "泓"]; })
2. Die Beziehung zwischen Anbieter, Service, Fabrik
Fabrik
factory ist sehr ähnlich wie service, der Unterschied besteht darin, dass service ein Singleton-Objekt in Angular ist. Wenn Sie also service verwenden müssen, verwenden Sie das Schlüsselwort new, um einen (und nur einen) Service zu erstellen. Factory ist eine gewöhnliche Funktion. Bei Bedarf handelt es sich lediglich um eine Methode zum Aufrufen einer gewöhnlichen Funktion. Sie kann verschiedene Formen von Daten zurückgeben, indem sie beispielsweise ein Sammlungsobjekt funktionaler Funktionen zurückgibt.
Definition:
let app = angular.module("app", []); // 这里可以注入 $http 等 Provider app.factory("Today", () => { let date = new Date(); return { year: date.getFullYear(), month: date.getMonth() + 1, day: date.getDate() }; });
Injektion verwenden:
app.controller("control", (Today) => { console.log(Today.year); console.log(Today.month); console.log(Today.day); });
service
service ist bei Verwendung ein Singleton-Objekt und auch ein Konstruktor. Aufgrund seiner Eigenschaften kann er nichts zurückgeben, da er mit dem Schlüsselwort new erstellt wird und im verwendet werden kann Controller Kommunikation und Dateninteraktion zwischen Controllern, da die Bereichskette des Controllers zerstört wird, wenn sie nutzlos ist (z. B. Routing verwenden, um zu einer anderen Seite zu springen, während ein anderer Controller verwendet wird)
Definition:
let app = angular.module("app", []); // 这里可以注入 $http 等 Provider // 注意这里不可以使用 arrow function // arrow function 不能作为 constructor app.service("Today", function() { let date = new Date(); this.year = date.getFullYear(); this.month = date.getMonth() + 1; this.day = date.getDate(); });
Injektion verwenden:
app.controller("control", (Today) => { console.log(Today.year); console.log(Today.month); console.log(Today.day); });
Anbieter
Anbieter Ja Was die zugrunde liegende Methode zur Erstellung des Dienstes betrifft, können wir verstehen, dass der Anbieter eine konfigurierbare Version des Dienstes ist. Wir können einige Parameter des Anbieters konfigurieren, bevor wir den Anbieter offiziell einfügen.
Definition:
let app = angular.module("app", []); // 这里可以注入 $http 等 Provider // 注意这里不可以使用 arrow function // arrow function 不能作为 constructor app.provider("Today", function() { this.date = new Date(); let self = this; this.setDate = (year, month, day) => { this.date = new Date(year, month - 1, day); } this.$get = () => { return { year: this.date.getFullYear(), month: this.date.getMonth() + 1, day: this.date.getDate() }; }; });
Injektion verwenden:
// 这里重新配置了今天的日期是 2015年2月15日 // 注意这里注入的是 TodayProvider,使用驼峰命名来注入正确的需要配置的 provider app.config((TodayProvider) => { TodayProvider.setDate(2015, 2, 15); }); app.controller("control", (Today) => { console.log(Today.year); console.log(Today.month); console.log(Today.day); });
3. Konflikt zwischen Lenker und Winkelsymbolauflösung
Szenario:
Wenn ich node.js als Server verwende und Lenker als Vorlagen-Engine verwendet wird, wenn node .js reagiert auf eine bestimmte URL und rendert diese, da ihre Vorlage { {} } als Variablen-Parsing-Symbol verwendet. In ähnlicher Weise verwendet Angular auch { {} } als Symbol für die variable Auflösung. Wenn also node.js die Seite rendert und die Variablen in { {} } nicht vorhanden sind, wird der Bereich gelöscht, und meine ursprüngliche Absicht ist dies Es wird verwendet für die Analyse von Angular anstelle von Handles. Gleichzeitig möchte ich auch weiterhin Handles verwenden, daher muss ich zu diesem Zeitpunkt das Standard-Parsing-Symbol {{} } von Angular neu definieren. Das heißt, verwenden Sie die Abhängigkeitsinjektion $interpolateProvider, um sie zu definieren, wie im folgenden Beispiel gezeigt:
app.config($interpolateProvider => { $interpolateProvider.startSymbol('{[{'); $interpolateProvider.endSymbol('}]}'); });
4. ng-annotate-loader
ng -annotate-loader wird auf das Entwicklungsszenario von Webpack + Angular angewendet. Es ist eine Lösung, um das Problem zu lösen, dass die Abhängigkeitsinjektion fehlschlägt und Fehler auftreten, nachdem Angular JS komprimiert wurde
Installation
$ npm install ng-annotate-loader --save-dev
Konfiguration
// webpack.config.js { test: /\.js?$/, exclude: /(node_modules|bower_components)/, loader: 'ng-annotate!babel?presets=es2015' },
Zwei-Wege-Datenbindung
Wenn wir nicht in Angular integrierte Ereignisse verwenden, führen Datenänderungen in $scope nicht zum Dirty-Checking-Zyklus von $digest. Dies führt dazu, dass die Ansicht beim Modellieren nicht synchron aktualisiert wird In diesem Fall müssen wir das Update aktiv selbst auslösen
HTML
<div>{{ foo }}</div> <button id="addBtn">go</button>
JavaScript
app.controller("control", ($scope) => { $scope.foo = 0; document.getElementById("addBtn").addEventListener("click", () => { $scope.foo++; }, false); })
Ganz offensichtlich ist die Absicht des Beispiels, dass foo die Ansicht vergrößert und aktualisiert, wenn auf die Schaltfläche geklickt wird. Tatsächlich wird jedoch $scope.foo geändert. aber die Ansicht wird nicht aktualisiert. Dies liegt daran, dass foo kein $watch zum Erkennen von Änderungen hat, was letztendlich $digest verursacht, also müssen wir $apply selbst auslösen oder ein $watch erstellen, um Datenänderungen auszulösen oder zu erkennen >
JavaScript (mit $apply)app.controller("control", ($scope) => { $scope.foo = 0; document.getElementById("addBtn").addEventListener("click", () => { $scope.$apply(function() { $scope.foo++; }); }, false); })
app.controller("control", ($scope) => { $scope.foo = 0; $scope.flag = 0; $scope.$watch("flag", (newValue, oldValue) => { // 当 $digest 循环检测 flag 时,如果新旧值不一致将调用该函数 $scope.foo = $scope.flag; }); document.getElementById("addBtn").addEventListener("click", () => { $scope.flag++; // 主动触发 $digest 循环 $scope.$digest(); }, false); })
function $apply(expr) { try { return $eval(expr); } catch (e) { $exceptionHandler(e); } finally { $root.$digest(); } }
Wenn während der Ausführung eine Ausnahme auftritt, führen Sie $ExceptionHandler(e) aus
Am Ende wird unabhängig vom Ergebnis eine $digest-Schleife ausgeführt