change detection anno domini 2016
TRANSCRIPT
IMPERATIVE AS HELL...
7. $("#first-one").css('background-color','green'); 8. $("#second-one").css('background-color','green'); 9. $("#third-one").css('background-color','green');
1. <button id="button">Click Me</button> 2. <div id="first-one"></div> 3. <div id="second-one"></div> 4. <div id="third-one"></div> 5. 6. $( "#button" ).click(function() {
10. }); 11.
MUTATOR FUNCTION
8. $scope.colorToGreen = function(){ 9. $scope.colorVar = "green" 10. }
1. <button ng-click="colorToGreen()">Click Me</button> 2. <div ng-style="{'background-color': colorVar}"></div> 3. <div ng-style="{'background-color': colorVar}"></div> 4. <div ng-style="{'background-color': colorVar}"></div> 5. 6. $scope.colorVar = "white" 7.
11.
EVENTS NOT CONTROLED BY ANGULAR.JS
15. setTimeout(function () { 16. $scope.message = "delayed message"; 17. $scope.$apply(); 18. }, 2000);
3. $scope.message = {} 4. 5. $watchList = [] 6. 7. scope.$watch('name', function(newValue, oldValue) { 8. scope.counter = scope.counter + 1; 9. }); 10. 11. angular.element(element).on(EVENT, function(){
12. $apply(); 13. }, 500)); 14.
19.
MONKEY PATCHING
23. Zone.setInterval() 24. Zone.setTimeout() 25. Zone.alert() 26. Zone.prompt() 27. Zone.requestAnimationFrame() 28. Zone.addEventListener() 29. Zone.removeEventListener() 30. XMLHttpRequest 31.
11. });
12. 13. zone.setTimeout = function(cb, time){ 14. let window = localWindowGlobal; 15. 16. nativeSetTimeout(function(){ 17. angularStuff(); 18. cb(); 19. }, time); 20. 21. } 22.
export function patchMethod(target: any, name: string, patchFn: (delegate: Function, delegateName: string, name: string) => (self: any, args: any[]) => any): Function { let proto = target; while (proto && !proto.hasOwnProperty(name)) { proto = Object.getPrototypeOf(proto); } if (!proto && target[name]) { // somehow we did not find it, but we can see it. This happens on IE for Window properties. proto = target; } const delegateName = zoneSymbol(name); let delegate: Function; if (proto && ! (delegate = proto[delegateName])) { delegate = proto[delegateName] = proto[name]; proto[name] = createNamedFn(name, patchFn(delegate, delegateName, name)); } return delegate; } https://github.com/angular/zone.js/blob/master/lib/common/utils.ts
26. <div style={style}></div>
15. }); 16. } 17. 18. render() { 19. const style = { 20. background: this.state.color, 21. }; 22. 23. return ( 24. <div> 25. <div style={style}></div>
27. <div style={style}></div> 28. <button style={styles} onClick={this.handleClick}>Click Me</button> 29. </div> 30. ); 31. } 32. } 33.
...RECONCILE EVERYTHING
9. Remove style color, Add style font-weight - difference
1. renderA: <div /> 2. renderB: <span /> 3. 4. Remove Node <div>, Insert Node <span> - full rerender 5. 6. renderA: <div style="{{color:red}}"/> 7. renderB: <div style="{{fontWeight:bold}}"/> 8.
10.
OVER AND OVER
1. while (op) { 2. var getter = getterFor(op.fieldName); 3. 4. var oldValue = op.value; 5. var newValue = getter(op.context); 6. 7. if (oldValue != newValue) { 8. op.value = newValue; 9. 10. var fn = reconcilationFunctionFor(op); 11. fn(oldValue, newValue)
12. }
POLIMORPHICAL STRUCTURE
10. checkWeapon(thor) 11. checkWeapon(cap)
1. function checkWeapon(hero) { 2. console.log(hero.weapon) 3. } 4. 5. // ... 6. 7. var thor = {weapon: 'hammer'} 8. var cap = {weapon: 'shield', citizenship: "America"} 9.
12.
...JUST ON THIS SPECIFIC OBJECT
7. if(hammer != this.previousHammer){ 8. this.previousHammer = hammer; 9. this.heroComponent.hammer = hammer; 10. }
1. <hero [weapon]="thor.hammer"></hero> 2. 3. Class Thor_ChangeDetector { 4. detectChanges() { 5. var thor = obj.thor; 6. var hammer = thor.hammer
11. } 12. } 13.
NEW OBJECT
9. x === y //false
1. var thor = {weapon: "hammer"} 2. var newThor = thor; 3. newThor.weapon = "shield" 4. x === y // true 5. 6. var ImmutableHero = Immutable.Record({ weapon: null }); 7. var thor = new ImmutableHero({ weapon: 'hammer'}); 8. var newThor = hero.set('weapon', 'shield');
10.
ANGULAR METADATA
1. @Component({changeDetection:ChangeDetectionStrategy.OnPush}) 2. class ImmutableHammerCmp { 3. hammer:Hammer; 4. } 5.
USE SHOULD COMPONENT UPDATE
5. this.shouldComponentUpdate = mx.shouldComponentUpdate.bind(this);
1. import mx from 'react-addons-pure-render-mixin'; 2. class FooComponent extends React.Component { 3. constructor(props) { 4. super(props);
6. } 7. 8. render() { 9. return <div className={this.props.className}>foo</div>; 10. } 11. } 12.
DEFINE OBSERVABLES
1. @Component({selector:'weapon'}) 2. class ObservableHeroCmp { 3. weapon:ObservableWeapons ; 4. } 5.