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 相关文章推荐
javascript最常用与实用的创建类的代码
Aug 12 Javascript
JavaScript事件委托实例分析
May 26 Javascript
基于Bootstrap的UI扩展 StyleBootstrap
Jun 17 Javascript
15位和18位身份证JS校验的简单实例
Jul 18 Javascript
AngularJS基础 ng-switch 指令简单示例
Aug 03 Javascript
使用Bootstrap + Vue.js实现添加删除数据示例
Feb 27 Javascript
JavaScript编写一个贪吃蛇游戏
Mar 09 Javascript
关闭Vue计算属性自带的缓存功能方法
Mar 02 Javascript
详解PHP后期静态绑定分析与应用
Mar 21 Javascript
在vue2.0中引用element-ui组件库的方法
Jun 21 Javascript
vue项目中使用vue-i18n报错的解决方法
Jan 13 Javascript
前端Electron新手入门教程详解
Jun 21 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
smarty的保留变量问题
2008/10/23 PHP
PHP syntax error, unexpected $end 错误的一种原因及解决
2008/10/25 PHP
基于PHP一些十分严重的缺陷详解
2013/06/03 PHP
php过滤输入操作之htmlentities与htmlspecialchars用法分析
2017/02/17 PHP
用JS操作FRAME中的IFRAME及其内容的实现代码
2008/07/26 Javascript
jquery获取下拉列表的值为null的解决方法
2011/03/18 Javascript
javascript跟随滚动效果插件代码(javascript Follow Plugin)
2013/08/03 Javascript
JavaScript判断密码强度(自写代码)
2013/09/06 Javascript
jquery解析xml字符串简单示例
2014/04/11 Javascript
javascript实现全角与半角字符的转换
2015/01/07 Javascript
Javascript毫秒数用法实例
2015/02/05 Javascript
JQuery中Text方法用法实例分析
2015/05/18 Javascript
JS实现的左侧竖向滑动菜单效果代码
2015/10/19 Javascript
微信小程序 网络API Websocket详解
2016/11/09 Javascript
jQuery弹出层插件popShow用法示例
2017/01/23 Javascript
详细讲解vue2+vuex+axios
2017/05/27 Javascript
30分钟快速入门掌握ES6/ES2015的核心内容(上)
2018/04/18 Javascript
node中短信api实现验证码登录的示例代码
2021/01/20 Javascript
[02:17]DOTA2亚洲邀请赛 RAVE战队出场宣传片
2015/02/07 DOTA
python连接字符串的方法小结
2015/07/13 Python
利用python程序帮大家清理windows垃圾
2017/01/15 Python
解决Matplotlib图表不能在Pycharm中显示的问题
2018/05/24 Python
python安装scipy的方法步骤
2019/06/26 Python
python opencv将图片转为灰度图的方法示例
2019/07/31 Python
详解Python 中的容器 collections
2020/08/17 Python
如何使用python-opencv批量生成带噪点噪线的数字验证码
2020/12/21 Python
大学生农村教师实习自我鉴定
2013/09/21 职场文书
销售主管竞聘书
2014/03/31 职场文书
应聘销售主管的求职信
2014/04/26 职场文书
巾帼建功标兵事迹材料
2014/05/11 职场文书
幼儿园教师工作总结2015
2015/04/02 职场文书
公司管理制度范本
2015/08/03 职场文书
Html5调用企业微信的实现
2021/04/16 HTML / CSS
Python 阶乘详解
2021/10/05 Python
SQL Server的存储过程与触发器以及系统函数和自定义函数
2022/04/10 SQL Server
Spring Boot 使用 Spring-Retry 进行重试框架
2022/04/24 Java/Android