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 相关文章推荐
IE php关于强制下载文件的代码
Aug 23 Javascript
js修改table中Td的值(定义td的双击事件)
Jan 10 Javascript
JavaScript中圆括号()和方括号[]的特殊用法疑问解答
Aug 06 Javascript
jQuery仿淘宝网产品品牌隐藏与显示效果
Sep 01 Javascript
AngularJS  $modal弹出框实例代码
Aug 24 Javascript
jQuery实现弹出带遮罩层的居中浮动窗口效果
Sep 12 Javascript
关于AngularJs数据的本地存储详解
Jan 20 Javascript
canvas绘图不清晰的解决方案
Feb 28 Javascript
Vue-cli中为单独页面设置背景色的实现方法
Feb 11 Javascript
微信小程序实践之动态控制组件的显示/隐藏功能
Jul 18 Javascript
微信小程序开发问题之wx.previewImage
Dec 25 Javascript
javascript canvas API内容整理
Feb 16 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实现权限管理功能示例
2017/09/22 PHP
Yii2框架自定义验证规则操作示例
2019/02/08 PHP
用jQuery打造TabPanel效果代码
2010/05/22 Javascript
JavaScript高级程序设计 读书笔记之九 本地对象Array
2012/02/27 Javascript
正则表达式搭配js轻松处理json文本方便而老古
2013/02/17 Javascript
cookie 最近浏览记录(中文escape转码)具体实现
2013/06/08 Javascript
js实现拉伸拖动iframe的具体代码
2013/08/03 Javascript
Jquery AJAX POST与GET之间的区别
2013/11/14 Javascript
js实现简单的购物车有图有代码
2014/05/26 Javascript
JavaScript中的原型和继承详解(图文)
2014/07/18 Javascript
javascript记住用户名和登录密码(两种方式)
2015/08/04 Javascript
Highcharts使用简例及异步动态读取数据
2015/12/30 Javascript
JQUERY的AJAX请求缓存里的数据问题处理
2016/02/23 Javascript
微信小程序教程系列之新建页面(4)
2017/04/17 Javascript
JavaScript用200行代码制作打飞机小游戏实例
2017/06/21 Javascript
微信小程序如何实现在线客服功能
2019/10/16 Javascript
vue 父组件通过v-model接收子组件的值的代码
2019/10/27 Javascript
python实现判断数组是否包含指定元素的方法
2015/07/15 Python
Python提取网页中超链接的方法
2016/09/18 Python
Python3 Random模块代码详解
2017/12/04 Python
python with提前退出遇到的坑与解决方案
2018/01/05 Python
Python实现判断字符串中包含某个字符的判断函数示例
2018/01/08 Python
Python字符串格式化%s%d%f详解
2018/02/02 Python
PyTorch CNN实战之MNIST手写数字识别示例
2018/05/29 Python
python 实现批量xls文件转csv文件的方法
2018/10/23 Python
英国领先品牌手动工具和电动工具供应商:Tooled Up
2018/11/24 全球购物
Perfume’s Club德国官网:在线购买香水
2019/04/08 全球购物
简历中的自我评价怎么写
2014/01/29 职场文书
亲子拓展活动方案
2014/02/20 职场文书
个人授权委托书范本
2014/04/03 职场文书
食品安全汇报材料
2014/08/18 职场文书
基层党组织建设整改方案
2014/09/16 职场文书
胡雪岩故居导游词
2015/02/06 职场文书
《梅花魂》教学反思
2016/02/18 职场文书
python 提取html文本的方法
2021/05/20 Python
深入理解Pytorch微调torchvision模型
2021/11/11 Python