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 相关文章推荐
msn上的tab功能Firefox对childNodes处理的一个BUG
Jan 21 Javascript
jQuery bind事件使用详解
May 05 Javascript
IE8中使用javascript动态加载CSS的解决方法
Jun 17 Javascript
JavaScript实现选择框按比例拖拉缩放的方法
Aug 04 Javascript
jquery实现左右无缝轮播图
Jul 31 Javascript
值得分享的JavaScript实现图片轮播组件
Nov 21 Javascript
基于react组件之间的参数传递(详解)
Sep 05 Javascript
Vue实现active点击切换方法
Mar 16 Javascript
浅谈发布订阅模式与观察者模式
Apr 09 Javascript
微信小程序使用Vant Weapp组件库的方法步骤
Aug 01 Javascript
微信小程序列表时间戳转换实现过程解析
Oct 12 Javascript
vue中使用element ui的弹窗与echarts之间的问题详解
Oct 25 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
搜索引擎技术核心揭密
2006/10/09 PHP
php中url传递中文字符,特殊危险字符的解决方法
2013/08/17 PHP
Windows下的PHP安装pear教程
2014/10/24 PHP
php实现源代码加密的方法
2015/07/11 PHP
PHP使用pear实现mail发送功能 windows环境下配置pear
2016/04/15 PHP
php 处理png图片白色背景色改为透明色的实例代码
2018/12/10 PHP
Laravel 微信小程序后端搭建步骤详解
2019/11/26 PHP
javascript中使用replaceAll()函数实现字符替换的方法
2010/12/25 Javascript
ASP中Sub和Function的区别说明
2020/08/30 Javascript
jQuery+CSS 实现随滚动条增减的汽水瓶中的液体效果
2011/09/26 Javascript
jquery.Jcrop结合JAVA后台实现图片裁剪上传实例
2016/11/05 Javascript
简单实现JavaScript弹幕效果
2020/08/27 Javascript
vue+webpack 打包文件 404 页面空白的解决方法
2018/02/28 Javascript
vue cli 3.0 使用全过程解析
2018/06/14 Javascript
微信小程序项目总结之点赞 删除列表 分享功能
2018/06/25 Javascript
vuex根据不同的用户权限展示不同的路由列表功能
2019/09/20 Javascript
python中range()与xrange()用法分析
2016/09/21 Python
详解django三种文件下载方式
2018/04/06 Python
Python cookbook(字符串与文本)针对任意多的分隔符拆分字符串操作示例
2018/04/19 Python
python 发送get请求接口详解
2020/11/17 Python
基础的CSS3弹性盒Flexbox布局使用实例
2016/04/08 HTML / CSS
美国网上花店:JustFlowers
2017/02/12 全球购物
Coach澳大利亚官方网站:美国著名时尚奢侈品牌
2017/05/24 全球购物
Amara美国站:英国高端家居礼品网站,世界各地的奢侈家具品牌
2017/07/26 全球购物
Dogeared官网:在美国手工制作的珠宝
2019/08/24 全球购物
半年思想汇报
2013/12/30 职场文书
预备党员入党思想汇报
2014/01/04 职场文书
老公给老婆的道歉信
2014/01/10 职场文书
师范教师毕业鉴定
2014/01/13 职场文书
《曹刿论战》教学反思
2014/03/02 职场文书
高中生的自我评价
2014/03/04 职场文书
元宵晚会主持词
2014/03/25 职场文书
社区平安建设方案
2014/05/25 职场文书
工作表扬信范文
2015/01/17 职场文书
2019年入党思想汇报
2019/03/25 职场文书
go select编译期的优化处理逻辑使用场景分析
2021/06/28 Golang