当前位置: 移动技术网 > IT编程>脚本编程>AngularJs > Angular通过指令动态添加组件问题

Angular通过指令动态添加组件问题

2019年05月28日  | 移动技术网IT编程  | 我要评论

之前自己写的公共组件,都是会先引入,需要调起的时候再通过service控制公共组件状态、值、回调函数什么的。但是有一些场景不适合这种方式,还是动态添加组件更加好。通过写过的一个小组件来总结下。

创建组件

  场景:鼠标移动到图标上时,展示解释性的说明文字。那就需要创建一个普通的tooltip组件。如下:

<aside class="hover-tip-wrapper">
 <span>{{tiptext}}</span>
</aside>
import { component, oninit } from '@angular/core';
@component({
 selector: 'app-hovertip',
 templateurl: './hovertip.component.html',
 styleurls: ['./hovertip.component.scss']
})
export class hovertipcomponent implements oninit {
 public tiptext: string;
 constructor() { }
 ngoninit() {
 }
}
.hover-tip-wrapper{
 width: max-content;
 position: absolute;
 height: 30px;
 line-height: 30px;
 bottom: calc(100% + 5px);
 right: calc( -10px - 100%);
 background-color: rgba(#000000,.8);
 padding: 0 5px;
 border-radius: 3px;
 &::after{
 content: '';
 position: absolute;
 height: 0;
 width: 0;
 border: 4px solid transparent;
 border-top-color: rgba(#000000,.8);
 left: 10px;
 top: 100%;
 }
 span {
 color: #ccc;
 font-size: 12px;
 }
}

  非常简单的一个组件,tiptext来接收需要展示的文字。

  需要注意的是,声明组件的时候,除了需要添加到declarations中外,还记得要添加到entrycomponents中。

entrycomponents: [hovertipcomponent],
declarations: [hovertipcomponent, hovertipdirective]

  那entrycomponents这个配置项是做什么的呢?看源码注释,大概意思就是:angular会为此配置项中的组件创建一个componentfactory,并存放在componentfactoryresolver中。动态添加组件时,需要用到组件工厂,所以此配置是必不可少的。

创建指令

  通过指令为目标元素绑定事件,控制创建组件、传递tiptext以及组件的销毁。

import { input , directive , viewcontainerref , componentref, componentfactory, hostlistener , componentfactoryresolver} from '@angular/core';
import { hovertipcomponent } from './hovertip.component';
@directive({
 selector: '[apphovertip]'
})
export class hovertipdirective {
 public hovertip: componentref<hovertipcomponent>;
 public factory: componentfactory<hovertipcomponent>;
 constructor(
 private viewcontainer: viewcontainerref,
 private resolver: componentfactoryresolver
 ) {
 // 获取对应的组件工厂
 this.factory = this.resolver.resolvecomponentfactory(hovertipcomponent);
 }
 @input('apphovertip') tiptext: string;
 
 // 绑定鼠标移入的事件
 @hostlistener('mouseenter') onmouseenter() {
   // 清空所有的view 
   this.viewcontainer.clear();
 // 创建组件
 this.hovertip = this.viewcontainer.createcomponent(this.factory);
 // 向组件实例传递参数
 this.hovertip.instance.tiptext = this.tiptext;
 }
 
 // 绑定鼠标移出时的事件
 @hostlistener('mouseleave') onmouseleave() {
 if (this.hovertip) {
  // 组件销毁
 this.hovertip.destroy();
 }
 }
}

  通过viewcontainerref类来管理视图,这里用到了创建组件。这个 专栏 解释的挺清楚的。这里用到了以下两个api,清除和创建。

  createcomponent方法接受componentfactoty类,创建后返回的componentref类,可以获取到组件实例(instance),控制组件销毁。

  大致思路是这样的,先获取到了hovertipcomponent组件对于的componentfactory,监听鼠标移入事件,在触发事件时,通过viewcontainerref类来创建组件,存下返回的组件componentref(获取实例,销毁组件时需要用到),向组件实例传递tiptext。监听鼠标移出事件,在事件触发时,销毁组件。

使用

  在目标元素是绑定指令,同时传递tiptext即可。

  可以正常的创建和销毁。

总结

  开始做的时候,主要是对这几个类比较懵,viewcontainerref、componentref、componentfactory、componentfactoryresolver等,看看源码,查查资料,总会梳理清楚的。

参考资料:

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网