之前自己写的公共组件,都是会先引入,需要调起的时候再通过service控制公共组件状态、值、回调函数什么的。但是有一些场景不适合这种方式,还是动态添加组件更加好。通过写过的一个小组件来总结下。
创建组件
场景:鼠标移动到图标上时,展示解释性的说明文字。那就需要创建一个普通的tooltip组件。如下:
<aside class="hover-tip-wrapper">
<span>{{tipText}}</span>
</aside>
HTML
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() {
} }
ts
.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:;
width:;
border: 4px solid transparent;
border-top-color: rgba(#000000,.8);
left: 10px;
top: 100%;
} span {
color: #ccc;
font-size: 12px;
}
}
scss
非常简单的一个组件,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等,看看源码,查查资料,总会梳理清楚的。
参考资料:
https://segmentfault.com/a/1190000008672478#articleHeader1
https://segmentfault.com/a/1190000009175508
Angular使用总结 --- 通过指令动态添加组件的更多相关文章
-
easyui 动态添加组件 要重新渲染
做项目时动态添加组件是常有的事,easyui动态添加组件时样式会失效,这是因为这个组件没有经过 easyui的解析器解析, 比如: <pre name="code" cl ...
-
使用js动态添加组件
在文章开始之前,我想说两点 1 自己初学js,文章的内容在大神看来可能就是不值一提,但是谁都是从hello world来的,望高 手不吝指教# 2 我知道这个标题起的比较蛋疼,大家看图就能说明问题 ...
-
vue2.0动态添加组件
方法一.<template> <input type="text" v-model='componentName'> <button @click=' ...
-
Android笔记(六十一)动态添加组件
想要一个功能,点击按钮,可以在已有的布局上,新添加一组组件. 动态的创建组件,本质上还是创建组件,只不过是在程序中根据逻辑来创建.大致步骤是找到要创建控件的位置,然后将要创建的组件添加进去. 看代码: ...
-
动态添加组件(XML)
1.利用LayoutInflater的inflate动态加载XMLmLinearLayout = (LinearLayout)findViewById(R.id.LinearLayout_ID);La ...
-
easyui 使用jquery动态添加组件样式问题
可以使用$.parser.parse();这个方法进行处理: 例如: $.parser.parse(); 表示对整个页面重新渲染,渲染完就可以看到easyui原来的样式了: var targe ...
-
[deviceone开发]-动态添加组件add方法的示例
一.简介 这个示例详细介绍ALayout的add方法的使用(原理也适用于Linearlayout),以及add上去的新ui和已有的ui如何数据交换,初学者推荐.二.效果图 三.相关下载 https:/ ...
-
svg web拓扑更新了,支持动态添加svg组件
版本1.0请点此 预览地址 https://svg.yaolunmao.top 如何使用 # 克隆项目 git clone https://github.com/yaolunmao/vue-webto ...
-
unity3d动态操作组件
利用范型,动态操作组件(添加或删除) e.AddComponent<CubeTranslate> ();//动态添加组件 Destroy (e.GetComponent<CubeTr ...
随机推荐
-
Android引导指示层的制作 (ViewStub + SharePreference)
引导指示界面是个什么鬼东西?一张图即明了:
-
Deep Learning 11_深度学习UFLDL教程:数据预处理(斯坦福大学深度学习教程)
理论知识:UFLDL数据预处理和http://www.cnblogs.com/tornadomeet/archive/2013/04/20/3033149.html 数据预处理是深度学习中非常重要的一 ...
-
Go学习记录
操作系统:Windows 一.下载 go官网:https://golang.org/go下载地址:https://golang.org/dl/ 二.安装 安装包有msi安装版本,以及zip压缩包版本. ...
-
java 堆栈 静态
所以静态变量和非静态变量的区别就在于静态变量可以用来计数,而非静态变量则不行. 理解了内存,就理解了一切,就理解了各种各样的语言.所有的语言无非都是这样:局部变量分配内存永远在栈里面,new出来的东西 ...
-
爬虫再探之mysql简单使用
在爬取数据量比较大时,用EXCEL存取就不太方便了,这里简单介绍一下python操作mysql数据库的一些操作.本人也是借助别人的博客学习的这些,但是找不到原来博客链接了,就把自己的笔记写在这里,这里 ...
-
黑马程序员——JAVA基础之构造函数,构造代码块
------- android培训.java培训.期待与您交流! ---------- 构造函数特点: 1. 函数名与类名相同 2. 不用定义返回值类型 3. 不可以写return语句 构造函数 ...
-
C# 控件双缓冲控制 ControlStyles 枚举详解
ControlStyles 枚举 .NET Framework 4 指定控件的样式和行为. 此枚举有一个 FlagsAttribute 特性,通过该特性可使其成员值按位组合. 命名空间: Sy ...
-
浅谈C语言中的联合体
联合体union 当多个数据须要共享内存或者多个数据每次仅仅取其一时.能够利用联合体(union).在C Programming Language 一书中对于联合体是这么描写叙述的: 1)联合体是一个 ...
-
SRM 447(1-250pt, 1-500pt)
DIV1 250 水题...略. DIV1 500 抽象题意:有一个图,指定其中亮点p1和p2,删掉途中其他的一些点,使得p1和p2最短路大于3. 解法:使得p1和p2最短路为2的点一定要删掉.然后, ...
-
Problem A: A + B
Problem A: A + BTime Limit: 1 Sec Memory Limit: 128 MBSubmit: 17 Solved: 10[Submit][Status][Web Boar ...