머리말
저는 최근에 Angularjs를 사용해 봤습니다. Knockout에 비해 Angularjs의 MVVM 프레임워크는 더 강력하고 복잡하지만 다양한 튜토리얼이 인터넷에 있습니다. 프로젝트에서 실제로 사용되는 것들이 때때로 다양한 함정에 직면하게 될 것입니다.
1.ng-repeat
ng-repeat는 요소가 반복적으로 출력되어야 함을 식별하는 데 사용되며, 반복 출력의 내용은 고유해야 합니다
<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. 공급자, 서비스, 공장
공장
factory는 서비스와 매우 유사합니다. 차이점은 서비스가 Angular의 싱글톤 개체라는 것입니다. 즉, 서비스를 사용해야 할 때 new 키워드를 사용하여 하나의(단 하나의) 서비스를 생성합니다. Factory는 필요할 때 일반 함수를 호출하는 방법일 뿐입니다. 예를 들어 함수 함수의 컬렉션 개체를 반환하여 사용할 수 있습니다.
정의:
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() }; });
주사 사용:
app.controller("control", (Today) => { console.log(Today.year); console.log(Today.month); console.log(Today.day); });
service
service는 사용될 때 싱글톤 객체이며 생성자이기도 합니다. 그 특성상 new 키워드를 사용하여 생성되고 다음에서 사용할 수 있기 때문입니다. 컨트롤러 컨트롤러 간의 통신 및 데이터 상호 작용, 컨트롤러의 범위 체인이 쓸모 없게 되면 파괴되기 때문입니다(예: 다른 컨트롤러를 사용하는 동안 라우팅을 사용하여 다른 컨트롤러를 사용하는 동안 다른 페이지로 이동)
정의:
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(); });
삽입 사용:
app.controller("control", (Today) => { console.log(Today.year); console.log(Today.month); console.log(Today.day); });
공급자
공급자 예 서비스의 기본 생성 방법에 관해서는 공급자가 서비스의 구성 가능한 버전이라는 것을 이해할 수 있습니다. 공급자를 공식적으로 주입하기 전에 공급자의 일부 매개 변수를 구성할 수 있습니다.
정의:
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() }; }; });
주사 사용:
// 这里重新配置了今天的日期是 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. 핸들바와 각도 기호 해상도 간의 충돌
시나리오:
node.js를 서버로 사용하고 핸들바를 템플릿 엔진으로 사용할 때 노드 .js는 템플릿이 {{} }를 변수 구문 분석 기호로 사용하기 때문에 특정 URL에 응답하고 렌더링합니다. 마찬가지로 각도도 {{} }를 가변 해상도 기호로 사용하므로 node.js가 페이지를 렌더링할 때 {{} }의 변수가 존재하지 않으면 해당 영역이 지워지는데 원래 의도는 이렇습니다. 핸들바 대신 Angle의 파싱을 위해 동시에 핸들바도 계속 사용하고 싶기 때문에 이번에는 Angle의 기본 { {} } 파싱 기호를 다시 정의해야 합니다. 즉, 다음 예와 같이 종속성 주입 $interpolateProvider를 사용하여 정의합니다.
app.config($interpolateProvider => { $interpolateProvider.startSymbol('{[{'); $interpolateProvider.endSymbol('}]}'); });
4. ng-annotate-loader
ng -annotate-loader는 webpack +angular 개발 시나리오에 적용됩니다.Angular 압축 후 의존성 주입이 실패하고 오류가 발생하는 문제를 해결하기 위한 솔루션입니다.
설치
$ npm install ng-annotate-loader --save-dev
구성
// webpack.config.js { test: /\.js?$/, exclude: /(node_modules|bower_components)/, loader: 'ng-annotate!babel?presets=es2015' },
5. 🎜>
<div>{{ foo }}</div> <button id="addBtn">go</button>JavaScript
app.controller("control", ($scope) => { $scope.foo = 0; document.getElementById("addBtn").addEventListener("click", () => { $scope.foo++; }, false); })분명히 이 예제의 의도는 버튼을 클릭하면 foo가 성장하고 View가 업데이트된다는 것입니다. 그러나 실제로는 $scope.foo가 변경됩니다. 그러나 뷰는 새로 고쳐지지 않습니다. foo에는 변경 사항을 감지하는 $watch가 없기 때문에 결국 $digest가 발생하므로 $apply를 직접 트리거하거나 $watch를 생성하여 데이터 변경 사항을 트리거하거나 감지해야 합니다. JavaScript($apply 사용)
app.controller("control", ($scope) => { $scope.foo = 0; document.getElementById("addBtn").addEventListener("click", () => { $scope.$apply(function() { $scope.foo++; }); }, false); })JavaScript($watch 및 $digest 사용)
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); })6. $watch(watchExpression, Listener, [objectEquality] )watchExpression 값이 변경될 때마다 호출되는 리스너 콜백 함수를 등록합니다watchExpression은 $digest가 실행될 때마다 호출되어 감지할 값을 반환합니다(다중일 때 동일한 값이 두 번 입력될 때 watchExpression은 자체 값을 변경해서는 안 됩니다. 그렇지 않으면 다중 $digest 루프가 발생할 수 있습니다. watchExpression은 멱등성)
function $apply(expr) { try { return $eval(expr); } catch (e) { $exceptionHandler(e); } finally { $root.$digest(); } }$eval(expr)을 사용하여 expr 표현식을 실행하세요.
결국 결과에 관계없이 $digest 루프가 실행됩니다