shibiaoz / blog

blog with node express mongo
1 stars 0 forks source link

angular操作dom #5

Open shibiaoz opened 7 years ago

shibiaoz commented 7 years ago

elementref, TemplateRef, ViewRef, ComponentRef ViewContainerRef directive renderer, https://segmentfault.com/a/1190000004969541 http://www.jianshu.com/p/d799838052e9

shibiaoz commented 6 years ago

插入dom操作

虽然@viewchild 可以获取dom的引入并且可以通过nativeelement 获取操作dom的api,不过angular 并不推荐这么做,而是推荐通过view 的容器插入view的操作. 可以通过ViewChild 获取TemplateRef 实例,tpl 是通过ng-template 写的不可见模版,并不回在模版开始的时候渲染出来,templateRef 实例调用createEmbeddedView 返回是view 的实例,然后viewcontainer 可以调用insert 方法把view 插入进容器

export class SampleComponent implements AfterViewInit {
    @ViewChild("vc", {read: ViewContainerRef}) vc: ViewContainerRef;
    @ViewChild("tpl") tpl: TemplateRef<any>;

    ngAfterViewInit() {
        let view = this.tpl.createEmbeddedView(null);
        this.vc.insert(view);
    }
}

看下viewcontainer 的方法,有获取dom 节点,插入/删除等方法. 任何DOM元素都可以用作视图容器。有趣的是,Angular不在元素内插入视图,而是在绑定到ViewContainer的元素之后附加它们。 这与路由器插座如何插入组件类似. 但是作为viewcontaineref 最好的候选者是ng-container,它被渲染为一个注释,所以用ng-container 不会引入额外的html

class ViewContainerRef {
  get element(): ElementRef
  get injector(): Injector
  get parentInjector(): Injector
  clear(): void
  get(index: number): ViewRef|null
  get length(): number
  createEmbeddedView<C>(templateRef: TemplateRef<C>, context?: C, index?: number): EmbeddedViewRef<C>
  createComponent<C>(componentFactory: ComponentFactory<C>, index?: number, injector?: Injector, projectableNodes?: any[][], ngModule?: NgModuleRef<any>): ComponentRef<C>
  insert(viewRef: ViewRef, index?: number): ViewRef
  move(viewRef: ViewRef, currentIndex: number): ViewRef
  indexOf(viewRef: ViewRef): number
  remove(index?: number): void
  detach(index?: number): ViewRef|null
}

看下templateref 类的方法,createEmbeddedView 返回的是视图的饮用

class TemplateRef<C> {
  get elementRef(): ElementRef
  createEmbeddedView(context: C): EmbeddedViewRef<C>
}
shibiaoz commented 6 years ago

动态加载组件

angular 提供一种较为简单的动态加载组件的方式,之前我们是通过componentFactoryResove 和viewcontaineref 实现动态加载组件的,也可以利用angular的一个指令实现动态加载,不过两种方式都需要把动态添加的组件加入到entryComponents,

html
<ng-container *ngComponentOutlet="componentTypeExpression"></ng-container>

js

import {
  ComOutletDemoComponent
} from '../../components/com-outlet-demo/com-outlet-demo.component';
componentTypeExpression;
  constructor() {
    this.componentTypeExpression = ComOutletDemoComponent;
    console.log('FirstComponent', 'constructor');
  }

具体更多复杂的策略请参考 https://angular.cn/api/common/NgComponentOutlet

shibiaoz commented 6 years ago

通过compile 动态加载template

http://www.felearn.com/dynamic-template-to-compile-dynamic-component/#0-sqq-1-41410-9737f6f9e09dfaf5d3fd14d775bfee85