动态创建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 相关文章推荐
做网页的一些技巧(续)
Feb 01 Javascript
Javascript下IE与Firefox下的差异兼容写法总结
Jun 18 Javascript
JS将秒换成时分秒实现代码
Sep 03 Javascript
Js参数值中含有单引号或双引号问题的解决方法
Nov 06 Javascript
学习使用bootstrap3栅格系统
Apr 12 Javascript
基于Bootstrap+jQuery.validate实现表单验证
May 30 Javascript
JavaScript用JSONP跨域请求数据实例详解
Jan 06 Javascript
详解jQuery中ajax.load()方法
Jan 25 Javascript
详解AngularJs HTTP响应拦截器实现登陆、权限校验
Apr 11 Javascript
vue项目实战总结篇
Feb 11 Javascript
angularJs自定义过滤器实现手机号信息隐藏的方法
Oct 08 Javascript
详解VUE项目中安装和使用vant组件
Apr 28 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去除重复字的实现代码
2011/09/16 PHP
php对大文件进行读取操作的实现代码
2013/01/23 PHP
实例介绍PHP中zip_open()函数用法
2019/02/15 PHP
PHP的Trait机制原理与用法分析
2019/10/18 PHP
基于jQuery的图片大小自动适应实现代码
2010/11/17 Javascript
jqeury eval将字符串转换json的方法
2011/01/20 Javascript
固定背景实现的背景滚动特效示例分享
2013/05/19 Javascript
用JS生成UUID的方法实例
2016/03/30 Javascript
Windows 系统下设置Nodejs NPM全局路径
2016/04/26 NodeJs
判断输入的字符串是否是日期格式的简单方法
2016/07/11 Javascript
jQuery+CSS3实现仿花瓣网固定顶部位置带悬浮效果的导航菜单
2016/09/21 Javascript
详谈表单重复提交的三种情况及解决方法
2017/08/16 Javascript
jQury Ajax使用Token验证身份实例代码
2017/09/22 Javascript
原生JS+HTML5实现跟随鼠标一起流动的粒子动画效果
2018/05/03 Javascript
原生js实现贪食蛇小游戏的思路详解
2019/11/26 Javascript
vue3 watch和watchEffect的使用以及有哪些区别
2021/01/26 Vue.js
Python中的pack和unpack的使用
2018/03/12 Python
python 自动去除空行的实例
2018/07/24 Python
python保存二维数组到txt文件中的方法
2018/11/15 Python
Python实现的简单线性回归算法实例分析
2018/12/26 Python
Python基础之文件读取的讲解
2019/02/16 Python
Django分页功能的实现代码详解
2019/07/29 Python
Python检查 云备份进程是否正常运行代码实例
2019/08/22 Python
完美解决ARIMA模型中plot_acf画不出图的问题
2020/06/04 Python
Python类型转换的魔术方法详解
2020/12/23 Python
HTML5实现音频和视频嵌入的方法
2018/08/22 HTML / CSS
写好自荐信的技巧
2013/11/08 职场文书
上班迟到检讨书
2014/01/10 职场文书
写给老婆的检讨书
2014/02/21 职场文书
签订劳动合同通知书
2015/04/16 职场文书
2015年机关纠风工作总结
2015/05/15 职场文书
2015年网络管理员工作总结
2015/05/21 职场文书
2016年度农村党员干部主题教育活动总结
2016/04/06 职场文书
nginx处理http请求实现过程解析
2021/03/31 Servers
详解Apache SkyWalking 告警配置指南
2021/04/22 Servers
Python进度条的使用
2021/05/17 Python