feat(scope): new and improved scope implementation

- Speed improvements (about 4x on flush phase)
- Memory improvements (uses no function closures)
- Break $eval into $apply, $dispatch, $flush
- Introduced $watch and $observe

Breaks angular.equals() use === instead of ==
Breaks angular.scope() does not take parent as first argument
Breaks scope.$watch() takes scope as first argument
Breaks scope.$set(), scope.$get are removed
Breaks scope.$config is removed
Breaks $route.onChange callback has not "this" bounded
This commit is contained in:
Misko Hevery
2011-03-23 09:33:29 -07:00
committed by Vojta Jina
parent 1f4b417184
commit 8f0dcbab80
60 changed files with 2539 additions and 1721 deletions

View File

@@ -20,24 +20,25 @@ describe("markups", function(){
it('should translate {{}} in text', function(){
compile('<div>hello {{name}}!</div>');
expect(sortedHtml(element)).toEqual('<div>hello <span ng:bind="name"></span>!</div>');
scope.$set('name', 'Misko');
scope.$eval();
scope.name = 'Misko';
scope.$flush();
expect(sortedHtml(element)).toEqual('<div>hello <span ng:bind="name">Misko</span>!</div>');
});
it('should translate {{}} in terminal nodes', function(){
compile('<select name="x"><option value="">Greet {{name}}!</option></select>');
scope.$flush();
expect(sortedHtml(element).replace(' selected="true"', '')).toEqual('<select name="x"><option ng:bind-template="Greet {{name}}!">Greet !</option></select>');
scope.$set('name', 'Misko');
scope.$eval();
scope.name = 'Misko';
scope.$flush();
expect(sortedHtml(element).replace(' selected="true"', '')).toEqual('<select name="x"><option ng:bind-template="Greet {{name}}!">Greet Misko!</option></select>');
});
it('should translate {{}} in attributes', function(){
compile('<div src="http://server/{{path}}.png"/>');
expect(element.attr('ng:bind-attr')).toEqual('{"src":"http://server/{{path}}.png"}');
scope.$set('path', 'a/b');
scope.$eval();
scope.path = 'a/b';
scope.$flush();
expect(element.attr('src')).toEqual("http://server/a/b.png");
});
@@ -94,57 +95,57 @@ describe("markups", function(){
it('should bind disabled', function() {
compile('<button ng:disabled="{{isDisabled}}">Button</button>');
scope.isDisabled = false;
scope.$eval();
scope.$flush();
expect(element.attr('disabled')).toBeFalsy();
scope.isDisabled = true;
scope.$eval();
scope.$flush();
expect(element.attr('disabled')).toBeTruthy();
});
it('should bind checked', function() {
compile('<input type="checkbox" ng:checked="{{isChecked}}" />');
scope.isChecked = false;
scope.$eval();
scope.$flush();
expect(element.attr('checked')).toBeFalsy();
scope.isChecked=true;
scope.$eval();
scope.$flush();
expect(element.attr('checked')).toBeTruthy();
});
it('should bind selected', function() {
compile('<select><option value=""></option><option ng:selected="{{isSelected}}">Greetings!</option></select>');
scope.isSelected=false;
scope.$eval();
scope.$flush();
expect(element.children()[1].selected).toBeFalsy();
scope.isSelected=true;
scope.$eval();
scope.$flush();
expect(element.children()[1].selected).toBeTruthy();
});
it('should bind readonly', function() {
compile('<input type="text" ng:readonly="{{isReadonly}}" />');
scope.isReadonly=false;
scope.$eval();
scope.$flush();
expect(element.attr('readOnly')).toBeFalsy();
scope.isReadonly=true;
scope.$eval();
scope.$flush();
expect(element.attr('readOnly')).toBeTruthy();
});
it('should bind multiple', function() {
compile('<select ng:multiple="{{isMultiple}}"></select>');
scope.isMultiple=false;
scope.$eval();
scope.$flush();
expect(element.attr('multiple')).toBeFalsy();
scope.isMultiple='multiple';
scope.$eval();
scope.$flush();
expect(element.attr('multiple')).toBeTruthy();
});
it('should bind src', function() {
compile('<div ng:src="{{url}}" />');
scope.url = 'http://localhost/';
scope.$eval();
scope.$flush();
expect(element.attr('src')).toEqual('http://localhost/');
});