refactor(render): use RenderElementRef in all renderer methods

BREAKING CHANGES:
- Almost all methods in `Renderer` now take a `RenderElementRef` instead
  of a `ViewRef` + `boundElementIndex`.
- These methods can be called with the `ElementRef` from the app side
  directly.

Closes #2706
Related to #2476
This commit is contained in:
Tobias Bosch
2015-06-23 11:21:56 -07:00
parent 2c3c235969
commit ba9fecd068
13 changed files with 139 additions and 127 deletions

View File

@ -771,9 +771,7 @@ export class ElementInjector extends TreeNode<ElementInjector> {
getComponent(): any { return this._strategy.getComponent(); }
getElementRef(): ElementRef {
return new ElementRef(new ViewRef(this._preBuiltObjects.view), this._proto.index);
}
getElementRef(): ElementRef { return this._preBuiltObjects.view.elementRefs[this._proto.index]; }
getViewContainerRef(): ViewContainerRef {
return new ViewContainerRef(this._preBuiltObjects.viewManager, this.getElementRef());

View File

@ -1,14 +1,20 @@
import {DOM} from 'angular2/src/dom/dom_adapter';
import {normalizeBlank} from 'angular2/src/facade/lang';
import {normalizeBlank, BaseException} from 'angular2/src/facade/lang';
import {ViewRef} from './view_ref';
import {resolveInternalDomView} from 'angular2/src/render/dom/view/view';
import {RenderViewRef, RenderElementRef} from 'angular2/src/render/api';
/**
* @exportedAs angular2/view
*/
export class ElementRef {
export class ElementRef implements RenderElementRef {
constructor(public parentView: ViewRef, public boundElementIndex: number) {}
get renderView() { return this.parentView.render; }
// TODO(tbosch): remove this once Typescript supports declaring interfaces
// that contain getters
set renderView(value: any) { throw new BaseException('Abstract setter'); }
/**
* Exposes the underlying DOM element.
* (DEPRECATED way of accessing the DOM, replacement coming)

View File

@ -21,6 +21,8 @@ import {ElementBinder} from './element_binder';
import {isPresent, isBlank, BaseException} from 'angular2/src/facade/lang';
import * as renderApi from 'angular2/src/render/api';
import {EventDispatcher} from 'angular2/src/render/api';
import {ViewRef} from './view_ref';
import {ElementRef} from './element_ref';
export class AppViewContainer {
// The order in this list matches the DOM order.
@ -40,6 +42,8 @@ export class AppView implements ChangeDispatcher, EventDispatcher {
componentChildViews: List<AppView> = null;
viewContainers: List<AppViewContainer>;
preBuiltObjects: List<PreBuiltObjects> = null;
elementRefs: List<ElementRef>;
ref: ViewRef;
/**
* The context against which data-binding expressions in this view are evaluated against.
@ -58,6 +62,11 @@ export class AppView implements ChangeDispatcher, EventDispatcher {
constructor(public renderer: renderApi.Renderer, public proto: AppProtoView,
protoLocals: Map<string, any>) {
this.viewContainers = ListWrapper.createFixedSize(this.proto.elementBinders.length);
this.elementRefs = ListWrapper.createFixedSize(this.proto.elementBinders.length);
this.ref = new ViewRef(this);
for (var i = 0; i < this.elementRefs.length; i++) {
this.elementRefs[i] = new ElementRef(this.ref, i);
}
this.locals = new Locals(null, MapWrapper.clone(protoLocals)); // TODO optimize this
}
@ -100,14 +109,16 @@ export class AppView implements ChangeDispatcher, EventDispatcher {
// dispatch to element injector or text nodes based on context
notifyOnBinding(b: BindingRecord, currentValue: any): void {
if (b.isElementProperty()) {
this.renderer.setElementProperty(this.render, b.elementIndex, b.propertyName, currentValue);
this.renderer.setElementProperty(this.elementRefs[b.elementIndex], b.propertyName,
currentValue);
} else if (b.isElementAttribute()) {
this.renderer.setElementAttribute(this.render, b.elementIndex, b.propertyName, currentValue);
this.renderer.setElementAttribute(this.elementRefs[b.elementIndex], b.propertyName,
currentValue);
} else if (b.isElementClass()) {
this.renderer.setElementClass(this.render, b.elementIndex, b.propertyName, currentValue);
this.renderer.setElementClass(this.elementRefs[b.elementIndex], b.propertyName, currentValue);
} else if (b.isElementStyle()) {
var unit = isPresent(b.propertyUnit) ? b.propertyUnit : '';
this.renderer.setElementStyle(this.render, b.elementIndex, b.propertyName,
this.renderer.setElementStyle(this.elementRefs[b.elementIndex], b.propertyName,
`${currentValue}${unit}`);
} else if (b.isTextNode()) {
this.renderer.setText(this.render, b.elementIndex, currentValue);
@ -134,7 +145,7 @@ export class AppView implements ChangeDispatcher, EventDispatcher {
}
invokeElementMethod(elementIndex: number, methodName: string, args: List<any>) {
this.renderer.invokeElementMethod(this.render, elementIndex, methodName, args);
this.renderer.invokeElementMethod(this.elementRefs[elementIndex], methodName, args);
}
// implementation of EventDispatcher#dispatchEvent

View File

@ -24,7 +24,7 @@ export class ViewContainerRef {
}
}
get(index: number): ViewRef { return new ViewRef(this._getViews()[index]); }
get(index: number): ViewRef { return this._getViews()[index].ref; }
get length(): number { return this._getViews().length; }

View File

@ -22,7 +22,7 @@ export class AppViewManager {
getComponentView(hostLocation: ElementRef): ViewRef {
var hostView = internalView(hostLocation.parentView);
var boundElementIndex = hostLocation.boundElementIndex;
return new ViewRef(hostView.componentChildViews[boundElementIndex]);
return hostView.componentChildViews[boundElementIndex].ref;
}
getViewContainer(location: ElementRef): ViewContainerRef {
@ -45,7 +45,7 @@ export class AppViewManager {
if (isBlank(elementIndex)) {
throw new BaseException(`Could not find variable ${variableName}`);
}
return new ElementRef(new ViewRef(componentView), elementIndex);
return componentView.elementRefs[elementIndex];
}
getComponent(hostLocation: ElementRef): any {
@ -69,7 +69,7 @@ export class AppViewManager {
this._utils.hydrateRootHostView(hostView, injector);
this._viewHydrateRecurse(hostView);
return new ViewRef(hostView);
return hostView.ref;
}
destroyRootHostView(hostViewRef: ViewRef) {
@ -98,14 +98,13 @@ export class AppViewManager {
var view = this._createPooledView(protoView);
this._renderer.attachViewInContainer(parentView.render, boundElementIndex, atIndex,
view.render);
this._renderer.attachViewInContainer(viewContainerLocation, atIndex, view.render);
this._utils.attachViewInContainer(parentView, boundElementIndex, contextView,
contextBoundElementIndex, atIndex, view);
this._utils.hydrateViewInContainer(parentView, boundElementIndex, contextView,
contextBoundElementIndex, atIndex, injector);
this._viewHydrateRecurse(view);
return new ViewRef(view);
return view.ref;
}
destroyViewInContainer(viewContainerLocation: ElementRef, atIndex: number) {
@ -126,8 +125,7 @@ export class AppViewManager {
// Right now we are destroying any special
// context view that might have been used.
this._utils.attachViewInContainer(parentView, boundElementIndex, null, null, atIndex, view);
this._renderer.attachViewInContainer(parentView.render, boundElementIndex, atIndex,
view.render);
this._renderer.attachViewInContainer(viewContainerLocation, atIndex, view.render);
return viewRef;
}
@ -137,9 +135,8 @@ export class AppViewManager {
var viewContainer = parentView.viewContainers[boundElementIndex];
var view = viewContainer.views[atIndex];
this._utils.detachViewInContainer(parentView, boundElementIndex, atIndex);
this._renderer.detachViewInContainer(parentView.render, boundElementIndex, atIndex,
view.render);
return new ViewRef(view);
this._renderer.detachViewInContainer(viewContainerLocation, atIndex, view.render);
return view.ref;
}
_createPooledView(protoView: viewModule.AppProtoView): viewModule.AppView {
@ -160,7 +157,7 @@ export class AppViewManager {
var binder = binders[binderIdx];
if (binder.hasStaticComponent()) {
var childView = this._createPooledView(binder.nestedProtoView);
this._renderer.attachComponentView(view.render, binderIdx, childView.render);
this._renderer.attachComponentView(view.elementRefs[binderIdx], childView.render);
this._utils.attachComponentView(view, binderIdx, childView);
}
}
@ -179,14 +176,15 @@ export class AppViewManager {
var view = viewContainer.views[atIndex];
this._viewDehydrateRecurse(view, false);
this._utils.detachViewInContainer(parentView, boundElementIndex, atIndex);
this._renderer.detachViewInContainer(parentView.render, boundElementIndex, atIndex,
this._renderer.detachViewInContainer(parentView.elementRefs[boundElementIndex], atIndex,
view.render);
this._destroyPooledView(view);
}
_destroyComponentView(hostView, boundElementIndex, componentView) {
this._viewDehydrateRecurse(componentView, false);
this._renderer.detachComponentView(hostView.render, boundElementIndex, componentView.render);
this._renderer.detachComponentView(hostView.elementRefs[boundElementIndex],
componentView.render);
this._utils.detachComponentView(hostView, boundElementIndex);
this._destroyPooledView(componentView);
}