Upload
da-14
View
231
Download
0
Embed Size (px)
Citation preview
- the less routine code the happier developers- good application structure two-way data binding- directives- testability- active community / cool documentation, etc...
var btn = document.getElementById("myBtn");
btn.addEventListener("click", onClick);
function onClick(evt) {
// some code
}
<button ng-click=”onClick($event)”></button>
element.on(‘click’, function(event){
var callback = function(){
fn(scope, {$event: event});
} scope.$apply(callback);
})
<span>{{myModel}}</span>
function myController($scope, $timeout) {
$scope.myModel = ‘value1’;
setTimeout(function(){
$scope.myModel = ‘value2’;
}, 500);
$timeout(function(){
$scope.myModel = ‘value2’;
}, 500);
}
scope.$watch(‘someModel2’,
callback);
{{someModel}}, ng-bind
ng-repeat, ng-model..
$timeout(fn) с нулевой
задержкой
scope.$evalAsync(fn)
$watch list $evalAsync list
step 1:function Scope() {}
step 2:function Scope() { this.$$watchers = [];}
step 3:Scope.prototype.$watch = function(watchFn, listenerFn) { var watcher = { watchFn: watchFn, listenerFn: listenerFn }; this.$$watchers.push(watcher);};
$watchList implementation
step 4:Scope.prototype.$digest = function() { _.forEach(this.$$watchers, function(watch) { watch.listenerFn(); }); };
step 5: Scope.prototype.$digest = function() { var self = this; _.forEach(this.$$watchers, function(watch) { var newValue = watch.watchFn(self); var oldValue = watch.last; if (newValue !== oldValue) { watch.listenerFn(newValue, oldValue, self); } watch.last = newValue; }); };
...$scope.$watch(‘myModel’, function(){ alert(‘My model was changed’);});
$scope.$watch(‘yourModel’, function(){ scope.myModel = ‘someValue’;});...
<input type=”text” ng-model=”yourModel” />
Scope.prototype.$digest = function() { var self = this; var dirty; do {
dirty = false; _.forEach(this.$$watchers, function(watch) { var newValue = watch.watchFn(self); var oldValue = watch.last; if (newValue !== oldValue) { watch.listenerFn(newValue, oldValue, self);
dirty = true; } watch.last = newValue; });
} while (dirty); };
DIRTY CHECK
step 1:function Scope() { this.$$watchers = []; this.$$asyncQueue = [];}
step 2: Scope.prototype.$evalAsync = function(expr) { var obj = {scope: this, expression: expr}; this.$$asyncQueue.push(obj);};
step 3:Scope.prototype.$digest = function() { while (this.$$asyncQueue.length) { var asyncTask = this.$$asyncQueue.shift(); this.$eval(asyncTask.expression); } ...};
$watchList implementation$evalAsync implementation
function myCtrl($scope, $rootScope) {
$scope.myModel = ‘value1’;
$scope.$evalAsync(function(){
console.log($scope.myModel);
});
$scope.myModel = ‘value2’;
}
$scope.$apply vs $scope.$digest
<body ng-app=”myApp”>{{rootMessage}} <div ng-controller=”myCtrl”>{{childMessage}}</div></body>function myCtrl($scope, $rootScope) { $rootScope.rootMessage = ‘root message’; $scope.childMessage = ‘child message’;
setTimeout(function(){$rootScope.rootMessage = ‘new root message’;
$scope.childMessage = ‘new child message’; $scope.apply(); // both model are re-rendered $scope.digest(); // only childMessage
}, 5000); }
setTimeout(function(){ $scope.apply(function(){//some code});}, 5000); }
$apply: function(expr) { try { return this.$eval(expr); } catch (e) { $exceptionHandler(e); } finally { try { $rootScope.$digest(); } catch (e) { $exceptionHandler(e); throw e; } }}
SOME OPTIMIZATION TIPS
- minimize watchers: - limit DOM filters
- use onetime binding when possible ng-bind=”::myModel” ng-repeat=”item in ::items” or bindonce if Angular < 1.3
- lightweight watch-functions and callbacks in watchers- ng-repeat=”item in items track by item.id” - $watchCollection instead of $watch with 3rd parameter equaled true- debounce ng-model <input ng-model=”myModel” ng-model-
options=”{debounce: 500}” />- use native JS or lodash (for example, simple ‘for’ loop instead of
angular.forEach )- use directive ng-bind instead of {{}};
$parse
$scope.$watch(function() {
return $scope.myModel;
}, callback);
$scope.$watch(‘myModel’, callback);
$watch: function(watchExp, listener, objectEquality){
var get = $parse(watchExp);...
}
$eval: function(expr, locals) {
return $parse(expr)(this, locals);
},
DEPENDENCY INJECTION IN ANGULAR
Dependency Injection is a software design pattern in which an object is given its
dependencies, rather than the object creating them itself.
angular.module(‘myApp’, []);
angular.module(‘myApp’)
.controller(‘myController’, myController);
function myController($scope, $timeout, myService) { // some code goes here }
function myController($timeout, $scope, myService) { // some code goes here }
ISSUES WITH IMPLICIT DEPENDENCESBefore minification:
angular.module(‘myApp’, []);
angular.module(‘myApp’)
.controller(‘myController’, myController);
function myController($scope, $timeout, myService) { // some code goes here }
After:
angular.module(‘myApp’,[]);angular.module(‘myApp’).controller(‘myController’,myController);function myController(l,o,p){...}
SOLUTIONSInline array annotation
$inject property annotation
angular.module(‘myApp’)
.controller(‘myController’, [‘$scope’, ‘myService’, myController]);
function myController($scope, myService) { ...}
angular.module(‘myApp’).controller(‘myController’, myController);
myController.$inject = [‘$scope’, ‘myService’];
function myController($scope, myService) { ...}
ОЙ, ВСЕ!