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轻松实现Ajax的实例代码
Aug 16 Javascript
javascript中length属性的探索
Jul 31 Javascript
jQuery打印图片pdf、txt示例代码
Jul 22 Javascript
JavaScript 事件对象介绍
Apr 13 Javascript
js实现tab切换效果实例
Sep 16 Javascript
AngularJS ngModel实现指令与输入直接的数据通信
Sep 21 Javascript
Vue如何引入远程JS文件
Apr 20 Javascript
实例详解JavaScript中setTimeout函数的执行顺序
Jul 12 Javascript
浅谈Vuejs Prop基本用法
Aug 17 Javascript
JavaScript实现简单图片轮播效果
Aug 21 Javascript
ExtJs整合Echarts的示例代码
Feb 27 Javascript
Angular6 Filter实现页面搜索的示例代码
Dec 02 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
有道搜索和IP138的IP的API接口(PHP应用)
2012/11/29 PHP
php session 写入数据库
2016/02/13 PHP
php+Memcached实现简单留言板功能示例
2017/02/15 PHP
javascript网页关闭时提醒效果脚本
2008/10/22 Javascript
jQuery EasyUI 中文API Button使用实例
2010/04/14 Javascript
Javascript中引用示例介绍
2014/02/21 Javascript
JS实现仿苹果底部任务栏菜单效果代码
2015/08/28 Javascript
jquery选择器简述
2015/08/31 Javascript
学习JavaScript设计模式之享元模式
2016/01/18 Javascript
js跨域资源共享 基础篇
2016/07/02 Javascript
学习掌握JavaScript中this的使用技巧
2016/08/29 Javascript
JavaScript String(字符串)对象的简单实例(推荐)
2016/08/31 Javascript
js对象浅拷贝和深拷贝详解
2016/09/05 Javascript
基于JS实现9种不同的面包屑和分布式多步骤导航效果
2017/02/21 Javascript
ionic实现下拉刷新载入数据功能
2017/05/11 Javascript
Vue中img的src属性绑定与static文件夹实例
2017/05/18 Javascript
JavaScript函数中的this四种绑定形式
2017/08/15 Javascript
本地搭建微信小程序服务器的实现方法
2017/10/27 Javascript
JQuery animate动画应用示例
2019/05/14 jQuery
[03:33]TI9战队采访 - Infamous
2019/08/20 DOTA
在Python的Django框架下使用django-tagging的教程
2015/05/30 Python
python实现远程通过网络邮件控制计算机重启或关机
2018/02/22 Python
Python中defaultdict与lambda表达式用法实例小结
2018/04/09 Python
Python爬虫使用浏览器cookies:browsercookie过程解析
2019/10/22 Python
pytorch 中的重要模块化接口nn.Module的使用
2020/04/02 Python
python解释器安装教程的方法步骤
2020/07/02 Python
Keras搭建自编码器操作
2020/07/03 Python
带你学习Python如何实现回归树模型
2020/07/16 Python
正宗的澳大利亚Ugg靴子零售商:UGG Express
2020/04/19 全球购物
数据库专业英语
2012/11/30 面试题
精选干货:Java精选笔试题附答案
2014/01/18 面试题
预备党员的自我评价
2014/03/12 职场文书
2014大学生全国两会学习心得体会
2014/03/13 职场文书
给校长的建议书200字
2014/05/16 职场文书
大学生个人年度总结范文
2015/02/15 职场文书
辞职信模板(中英文版)
2015/02/27 职场文书