动态创建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自动显示最后更新时间
Mar 15 Javascript
JavaScipt基本教程之JavaScript语言的基础
Jan 16 Javascript
Javascript 写的简单进度条控件
Jan 22 Javascript
jQuery live
May 15 Javascript
JS操作select下拉框动态变动(创建/删除/获取)
Jun 02 Javascript
js 获取、清空input type=&quot;file&quot;的值(示例代码)
Dec 24 Javascript
深入分析下javascript中的[]()+!
Jul 07 Javascript
Angular发布1.5正式版,专注于向Angular 2的过渡
Feb 18 Javascript
JS给swf传参数的实现方法
Sep 13 Javascript
jQuery实现选项卡功能(两种方法)
Mar 08 Javascript
微信小程序 POST请求的实例详解
Sep 29 Javascript
记录vue项目中遇到的一点小问题
May 14 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 select,radio和checkbox默认选择的实现方法
2010/05/15 PHP
PHP实现对文本数据库的常用操作方法实例演示
2014/07/04 PHP
优化WordPress的Google字体以加速国内服务器上的运行
2015/11/24 PHP
php封装好的人民币数值转中文大写类
2015/12/20 PHP
jQuery+PHP实现图片上传并提交功能
2020/07/27 PHP
jQuery getJSON 处理json数据的代码
2010/07/26 Javascript
与jquery serializeArray()一起使用的函数,主要来方便提交表单
2011/01/31 Javascript
JQuery的$命名冲突详细解析
2013/12/28 Javascript
深入理解Javascript里的依赖注入
2014/03/19 Javascript
JavaScript 继承详解(六)
2016/10/11 Javascript
Angular JS 生成动态二维码的方法
2017/02/23 Javascript
JS判断时间段的实现代码
2017/06/14 Javascript
JavaScript学习笔记之惰性函数示例详解
2017/08/27 Javascript
详解React开发必不可少的eslint配置
2018/02/05 Javascript
JS实现访问DOM对象指定节点的方法示例
2018/04/04 Javascript
浅谈Vue2.4.0 $attrs与inheritAttrs的具体使用
2020/03/08 Javascript
nestjs返回给前端数据格式的封装实现
2021/02/22 Javascript
[01:16]DOTA2小知识课堂 Ep.03 芒果树无伤肉山
2019/12/05 DOTA
Python translator使用实例
2008/09/06 Python
python实现下载整个ftp目录的方法
2017/01/17 Python
PyCharm 设置SciView工具窗口的方法
2019/01/15 Python
python 调用钉钉机器人的方法
2019/02/20 Python
Python使用paramiko操作linux的方法讲解
2019/02/25 Python
python 的topk算法实例
2020/04/02 Python
在tensorflow下利用plt画论文中loss,acc等曲线图实例
2020/06/15 Python
python按照list中字典的某key去重的示例代码
2020/10/13 Python
详解Html5中video标签那些属性和方法
2019/07/01 HTML / CSS
HTML5实现锚点时请使用id取代name
2013/09/06 HTML / CSS
美国知名的时尚购物网站:Anthropologie
2016/12/22 全球购物
远程学习的教学用品和家庭学习资源:Really Good Stuff
2020/04/27 全球购物
三八妇女节演讲稿
2014/05/27 职场文书
国庆65周年演讲稿:回首往昔,展望未来
2014/09/21 职场文书
2014乡镇干部对照检查材料思想汇报
2014/09/26 职场文书
六年级学生期末评语
2014/12/26 职场文书
社区扶贫帮困工作总结
2015/05/20 职场文书
如何写好开幕词?
2019/06/24 职场文书