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


Posted in Javascript onJuly 09, 2018

之前自己写的公共组件,都是会先引入,需要调起的时候再通过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中。动态添加组件时,需要用到组件工厂,所以此配置是必不可少的。

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

创建指令

通过指令为目标元素绑定事件,控制创建组件、传递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,清除和创建。

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

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

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

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

使用

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

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

可以正常的创建和销毁。

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

总结

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

参考资料:

Javascript 相关文章推荐
Jquery 的outerHeight方法使用介绍
Sep 11 Javascript
Javascript中call与apply的学习笔记
Sep 22 Javascript
jquery实现表单验证简单实例演示
Nov 23 Javascript
jquery中ajax跨域方法实例分析
Dec 18 Javascript
浅谈angularJS中的事件
Jul 12 Javascript
angular基于路由控制ui-router实现系统权限控制
Sep 27 Javascript
seajs模块之间依赖的加载以及模块的执行
Oct 21 Javascript
angularJs使用$watch和$filter过滤器制作搜索筛选实例
Jun 01 Javascript
详解React中的组件通信问题
Jul 31 Javascript
JavaScript实现图片懒加载的方法分析
Jul 05 Javascript
js+html5 canvas实现ps钢笔抠图
Apr 28 Javascript
微信小程序 checkbox使用实例解析
Sep 09 Javascript
js实现左右两侧浮动广告
Jul 09 #Javascript
vue-router中scrollBehavior的巧妙用法
Jul 09 #Javascript
JavaScript解决浮点数计算不准确问题的方法分析
Jul 09 #Javascript
Vue自定义指令封装节流函数的方法示例
Jul 09 #Javascript
JavaScript实现创建自定义对象的常用方式总结
Jul 09 #Javascript
vue-cli配置环境变量的方法
Jul 09 #Javascript
JS逻辑运算符短路操作实例分析
Jul 09 #Javascript
You might like
php zend解密软件绿色版测试可用
2008/04/14 PHP
php实现斐波那契数列的简单写法
2014/07/19 PHP
自定义session存储机制避免会话保持问题
2014/10/08 PHP
php判断一个数组是否为有序的方法
2015/03/27 PHP
php7安装yar扩展的方法详解
2017/08/03 PHP
Laravel5.4简单实现app接口Api Token认证方法
2019/08/29 PHP
ThinkPHP 框架实现的读取excel导入数据库操作示例
2020/04/14 PHP
Laravel 修改验证异常的响应格式实例代码详解
2020/05/25 PHP
Firefox下提示illegal character并出现乱码的原因
2010/03/25 Javascript
javascript 模式设计之工厂模式详细说明
2010/05/10 Javascript
JavaScript之IE的fireEvent方法详细解析
2013/11/20 Javascript
jQuery中验证表单提交方式及序列化表单内容的实现
2014/01/06 Javascript
微信小程序 条件渲染详解
2016/10/09 Javascript
javaScript+turn.js实现图书翻页效果实例代码
2017/02/16 Javascript
图解Javascript——作用域、作用域链、闭包
2017/03/21 Javascript
使用JS动态显示文本
2017/09/09 Javascript
详解angularjs 学习之 scope作用域
2018/01/15 Javascript
微信小程序实现原生步骤条
2019/07/25 Javascript
解决vue打包报错Unexpected token: punc的问题
2020/10/24 Javascript
Vue+penlayers实现多边形绘制及展示
2020/12/24 Vue.js
Python中列表和元组的使用方法和区别详解
2020/12/30 Python
Python中的命令行参数解析工具之docopt详解
2017/03/27 Python
Django + Uwsgi + Nginx 实现生产环境部署的方法
2018/06/20 Python
Python绘制KS曲线的实现方法
2018/08/13 Python
python生成器与迭代器详解
2019/01/01 Python
Python+OpenCV图片局部区域像素值处理详解
2019/01/23 Python
Django Aggregation聚合使用方法解析
2019/08/01 Python
基于python实现复制文件并重命名
2020/09/16 Python
Canvas在超级玛丽游戏中的应用详解
2021/02/06 HTML / CSS
土木工程毕业生自荐信
2013/09/21 职场文书
《落花生》教学反思
2014/02/25 职场文书
合作协议书
2014/04/23 职场文书
防火标语大全
2014/10/06 职场文书
惹女朋友生气检讨书
2015/05/06 职场文书
初中数学教学反思范文
2016/02/17 职场文书
意外事故赔偿协议书
2016/03/22 职场文书