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 相关文章推荐
js 替换
Feb 19 Javascript
Array.prototype.slice 使用扩展
Jun 09 Javascript
javascript下string.format函数补充
Aug 24 Javascript
JS对象与json字符串格式转换实例
Oct 28 Javascript
AngularJS内置指令
Feb 04 Javascript
js实现使用鼠标拖拽切换图片的方法
May 04 Javascript
javascript中返回顶部按钮的实现
May 05 Javascript
jQuery实现图片左右滚动特效
Apr 20 Javascript
JavaScript中获取纯正的undefined的方法
Mar 06 Javascript
Vue制作Todo List网页
Apr 26 Javascript
vue.js组件vue-waterfall-easy实现瀑布流效果
Aug 22 Javascript
JavaScript实现好看的跟随彩色气泡效果
Feb 06 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上传中文文件名乱码问题处理方案
2015/02/03 PHP
PHP实现仿百度文库,豆丁在线文档效果(word,excel,ppt转flash)
2016/03/10 PHP
XML+XSL 与 HTML 两种方案的结合
2007/04/22 Javascript
Prototype Class对象学习
2009/07/19 Javascript
JavaScript 利用Cookie记录用户登录信息
2009/12/08 Javascript
JavaScript中变量提升 Hoisting
2012/07/03 Javascript
自己写的兼容ie和ff的在线文本编辑器类似ewebeditor
2012/12/12 Javascript
ANT 压缩(去掉空格/注释)JS文件可提高js运行速度
2013/04/15 Javascript
原生js实现半透明遮罩层效果具体代码
2013/06/06 Javascript
快速学习jQuery插件 jquery.validate.js表单验证插件使用方法
2015/12/01 Javascript
JavaScript编写点击查看大图的页面半透明遮罩层效果实例
2016/05/09 Javascript
jQuery Dialog对话框事件用法实例分析
2016/05/10 Javascript
JavaScript读二进制文件并用ajax传输二进制流的方法
2016/07/18 Javascript
使用JavaScript判断手机浏览器是横屏还是竖屏问题
2016/08/02 Javascript
jQuery Validate 相关参数及常用的自定义验证规则
2017/03/06 Javascript
angularJS实现动态添加,删除div方法
2018/02/27 Javascript
如何以Angular的姿势打开Font-Awesome详解
2018/04/22 Javascript
深入浅析Vue.js 中的 v-for 列表渲染指令
2018/11/19 Javascript
详解Vue源码中一些util函数
2019/04/24 Javascript
vue实现的上拉加载更多数据/分页功能示例
2019/05/25 Javascript
js实现简易计算器功能
2019/10/18 Javascript
js使用文档就绪函数动态改变页面内容示例【innerHTML、innerText】
2019/11/07 Javascript
JS绘图Flot如何实现动态可刷新曲线图
2020/10/16 Javascript
浅谈Python中chr、unichr、ord字符函数之间的对比
2016/06/16 Python
python通过elixir包操作mysql数据库实例代码
2018/01/31 Python
利用python numpy+matplotlib绘制股票k线图的方法
2019/06/26 Python
在pycharm下设置自己的个性模版方法
2019/07/15 Python
Python使用itchat 功能分析微信好友性别和位置
2019/08/05 Python
python 变量初始化空列表的例子
2019/11/28 Python
python Scrapy爬虫框架的使用
2021/01/21 Python
html5 浏览器支持 如何让所有的浏览器都支持HTML5标签样式
2012/12/07 HTML / CSS
泰国Robinson百货官网:购买知名品牌的商品
2020/02/08 全球购物
机械化及自动化毕业生的自我评价分享
2013/11/06 职场文书
计算机个人求职信范例
2014/01/24 职场文书
大班亲子运动会方案
2014/06/10 职场文书
药剂专业自荐书
2014/06/20 职场文书