动态创建Angular组件实现popup弹窗功能


Posted in Javascript onSeptember 15, 2017

起步: 直接使用ngIf

把弹窗的DOM直接放在页面底下隐藏,通过ngIf这样的指令控制其显示。

改进: 封装成angular模块,通过服务控制其显示

直接使用ngIf的话,让人不爽的地方就在于不够通用,每个页面都得加DOM。改进的话可以把比较通用的一些DOM封装成组件,统一添加到全局页面中,并将显示的控制交给一个angular服务来控制其显示。

比如定义了两个组件(DialogComponent, AlertComponent),将他们都添加到AppComponent下,然后提供一个PopupService来控制组件的显示,并支持传递参数进去。

仅通过控制显示的方式仍不够通用且存在耦合

将弹窗组件封装然后使用服务来控制显示的方法看上去已经比较通用了,不过还存在两个尴尬的问题:

  1. 仍然需要在页面的某个地方放置一个弹窗组件,比如叫做PopupComponent,此组件负责渲染出默认隐藏的一些通用弹窗子组件,才能进行显示控制实现弹窗能力。
  2. 如果想要弹出一个自定义窗口的话就只能回到最上面另外写DOM放到需要弹出自定义弹窗的位置上,或者将自定义的标签通过innerHtml指令传入(富文本方式)。

由此可见这样的弹窗能力并没有做到非常通用,且必须手动放置弹窗插座(姑且这么叫)以致多了一处耦合。

动态创建弹窗

最理想的方式应该是: 在想要弹个窗口出来时直接一行代码把窗口弹出来,不用事先在哪里先把这个弹窗写好(或者说这一步不应该由弹窗控件的使用者来做,弹窗控件应该要自动完成这件事)。

而这一能力就涉及到angular的动态创建组件的能力了。

官网给出的用法

angular的官方文档中就有关于动态创建组件的用法。不过其使用的是ViewContainerRef服务,此服务提供了createComponent方法来在指定的视图容器下动态创建一个组件出来。

不过ViewContainerRef的尴尬点是只能在具体的指令、组件中使用,也就是说,必须告诉它打算在哪个地方创建新组建,这不还是需要实现创建好一个“弹窗插座”出来,才可以在这个“插座”中动态创建组件。

那有什么办法可以不给定视图容器而创建出组建来,通俗地讲问题就是: 不是在指令或者组件中创建组件,而是在服务中创建出组件,还要让这个组件显示到页面上去。

组建工厂——组件真正的创建者

在组件中创建组件的核心代码分两步:

创建组件工厂

let componentFactory = this.componentFactoryResolver.resolveComponentFactory(待创建组件);

把工厂提供给容器创建出组件

let componentRef = viewContainerRef.createComponent(componentFactory);

现在的问题在于,在服务中得不到viewContainerRef,工厂倒是能创建成功。

其实有工厂了已经足够了,查看componentFactory提供的成员里面包含了一个create方法,顾名思义这应该就是用来创建组件的了。

create方法有个必选参数类型为Injector,顾名思义就是注入器,即这个创建的组件打算注入些什么服务进去,暴力点直接写null也没问题。

直接使用工厂创建组件返回的同样是一个ComponentRef类型的引用,可见此时组件确实是创建出来了,但是还没有将其插入到视图中去。此时可以再暴力一点,直接用原生DOM操作插入到body标签的末尾去:

window.document.body.appendChild(
  this.getComponentRootNode(componentRef)
);
this.appRef.attachView(componentRef); // 注入ApplicationRef服务后使用
// ...
private getComponentRootNode(componentRef: ComponentRef<any>): HTMLElement {
  return (componentRef.hostView as EmbeddedViewRef<any>).rootNodes[0] as HTMLElement;
}
// ...

此办法是笔者从Material2的茫茫源代码中找到的,Google自己都直接这么插,那就放心使用了。这里不得不赞叹Material2中Dialog模块的实现,实在是有够复杂。

总结

本文主要在讲思路,扯到最后才开始要进入主题来动态创建组件,不过仅仅是创建出组件并添加到DOM中去还只是第一步,一个健壮的弹窗模块(Material2那样的)还得有一套完善的交互能力,比如弹出和关闭时的订阅和传值,这些就要通过注入服务到组件中来实现了,限于篇幅将在下一篇文章中回归实际实现一个通过动态创建组件实现的弹窗模块出来。

以上所述是小编给大家介绍的动态创建Angular组件实现popup弹窗功能,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!

Javascript 相关文章推荐
用JavaScript和注册表脚本实现右键收藏Web页选中文本
Jan 28 Javascript
仿新浪微博登陆邮箱提示效果的js代码
Aug 02 Javascript
jquery实现的一个文章自定义分段显示功能
May 23 Javascript
JS实现来回出现文字的状态栏特效代码
Oct 31 Javascript
JavaScript数据推送Comet技术详解
Apr 07 Javascript
js HTML5 Canvas绘制转盘抽奖
Sep 13 Javascript
Bootstrap基本插件学习笔记之轮播幻灯片(23)
Dec 08 Javascript
JavaScript取得gridview中获取checkbox选中的值
Jul 24 Javascript
原生js检测页面加载完毕的实例
Sep 11 Javascript
Vue使用NPM方式搭建项目
Oct 25 Javascript
js实现图片粘贴到网页
Dec 06 Javascript
JS访问对象两种方式区别解析
Aug 29 Javascript
Vue2.0基于vue-cli+webpack Vuex的用法(实例讲解)
Sep 15 #Javascript
angular4模块中给标签添加背景图的实现方法
Sep 15 #Javascript
基于Vue生产环境部署详解
Sep 15 #Javascript
基于Vue单文件组件详解
Sep 15 #Javascript
json2.js 入门教程之使用方法与实例分析
Sep 14 #Javascript
php main 与 iframe 相互通讯类(js+php同域/跨域)
Sep 14 #Javascript
iframe与主框架跨域相互访问实现方法
Sep 14 #Javascript
You might like
PHP中获取变量的变量名的一段代码的bug分析
2011/07/07 PHP
PHP如何将log信息写入服务器中的log文件
2015/07/29 PHP
解决php的“It is not safe to rely on the system’s timezone settings”问题
2015/10/08 PHP
CodeIgniter视图使用注意事项
2016/01/20 PHP
PHP上传图片时判断上传文件是否为可用图片的方法
2016/10/20 PHP
laravel请求参数校验方法
2019/10/10 PHP
js 程序执行与顺序实现详解
2013/05/13 Javascript
jquery禁用右键示例
2014/04/28 Javascript
Javascript学习笔记之函数篇(五) : 构造函数
2014/11/23 Javascript
深入浅出理解javaScript原型链
2015/05/09 Javascript
JS实现仿FLASH效果的竖排导航代码
2015/09/15 Javascript
jquery实现网页定位导航
2016/08/23 Javascript
微信小程序  checkbox组件详解及简单实例
2017/01/10 Javascript
vue脚手架搭建过程图解
2018/06/06 Javascript
Vue父子组件之间的通信实例详解
2018/09/28 Javascript
深入理解JavaScript 中的执行上下文和执行栈
2018/10/23 Javascript
微信小程序入口场景的问题集合与相关解决方法
2019/06/26 Javascript
简单说明Python中的装饰器的用法
2015/04/24 Python
Python的几个高级语法概念浅析(lambda表达式闭包装饰器)
2016/05/28 Python
Python同步遍历多个列表的示例
2019/02/19 Python
Python使用pyautocad+openpyxl处理cad文件示例
2019/07/11 Python
python使用socket 先读取长度,在读取报文内容示例
2019/09/26 Python
python实现输入的数据在地图上生成热力图效果
2019/12/06 Python
python PIL/cv2/base64相互转换实例
2020/01/09 Python
python+selenium定时爬取丁香园的新型冠状病毒数据并制作出类似的地图(部署到云服务器)
2020/02/09 Python
python GUI库图形界面开发之PyQt5不规则窗口实现与显示GIF动画的详细方法与实例
2020/03/09 Python
在jupyter notebook 添加 conda 环境的操作详解
2020/04/10 Python
Python猫眼电影最近上映的电影票房信息
2020/09/18 Python
全球最大的网上自行车商店:Chain Reaction Cycles
2016/12/02 全球购物
Hurley官方网站:扎根于海滩生活方式的全球青年文化品牌
2020/05/18 全球购物
Clos19英国:高档香槟、葡萄酒和烈酒在线购物平台
2020/07/10 全球购物
开发中都用到了那些设计模式?用在什么场合?
2014/08/21 面试题
汇源肾宝广告词
2014/03/20 职场文书
教育系统干部作风整顿心得体会
2014/09/09 职场文书
2019最新激励员工口号大全!
2019/06/28 职场文书
PyTorch 如何检查模型梯度是否可导
2021/06/05 Python