动态创建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 异步调用框架 (Part 6 - 实例 &amp; 模式)
Aug 04 Javascript
JavaScript中的作用域链和闭包
Jun 30 Javascript
深入理解javascript原型链和继承
Sep 23 Javascript
基于js与flash实现的网站flv视频播放插件代码
Oct 14 Javascript
jquery中change()用法实例分析
Feb 06 Javascript
jquery获取复选框checkbox的值的简单实现方法
May 26 Javascript
jquery.Jcrop结合JAVA后台实现图片裁剪上传实例
Nov 05 Javascript
JS实现本地存储信息的方法(基于localStorage与userData)
Feb 18 Javascript
微信小程序实现保存图片到相册功能
Nov 30 Javascript
Vue 理解之白话 getter/setter详解
Apr 16 Javascript
electron-vue利用webpack打包实现多页面的入口文件问题
May 12 Javascript
JS如何调用WebAssembly编译出来的.wasm文件
Nov 05 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制作的意见反馈表源码
2007/03/11 PHP
微信开发之获取JSAPI TICKET
2017/07/07 PHP
PHP操作Redis常用技巧总结
2018/04/24 PHP
Js 获取HTML DOM节点元素的方法小结
2009/04/24 Javascript
prettify 代码高亮着色器google出品
2010/12/28 Javascript
JS简单实现登陆验证附效果图
2013/11/19 Javascript
JS在可编辑的div中的光标位置插入内容的方法
2014/11/20 Javascript
Javascript的表单验证-初识正则表达式
2016/03/18 Javascript
jQuery解决IE6、7、8不能使用 JSON.stringify 函数的问题
2016/05/31 Javascript
浅谈js函数的多种定义方法与区别
2016/11/29 Javascript
Angularjs自定义指令实现三级联动 选择地理位置
2017/02/13 Javascript
脚本div实现拖放功能(两种)
2017/02/13 Javascript
NodeJS配置HTTPS服务实例分享
2017/02/19 NodeJs
简单了解node npm cnpm的具体使用方法
2019/02/27 Javascript
vuejs数据超出单行显示更多,点击展开剩余数据实例
2019/05/05 Javascript
jQuery层叠选择器用法实例分析
2019/06/28 jQuery
NProgress显示顶部进度条效果及使用详解
2019/09/21 Javascript
nuxt 路由、过渡特效、中间件的实现代码
2020/11/06 Javascript
[01:43]倾听DOTA2英雄之声 魅惑魔女国服配音鉴赏
2013/06/06 DOTA
[05:06]TI4西雅图DOTA2前线报道 海涛密探LGD训练
2014/07/09 DOTA
[03:45]Newbee战队出征西雅图 决战2016国际邀请赛
2016/08/02 DOTA
[58:15]2018DOTA2亚洲邀请赛 4.1 小组赛 A组 NB vs Liquid
2018/04/02 DOTA
深入讲解Java编程中类的生命周期
2016/02/05 Python
mac安装scrapy并创建项目的实例讲解
2018/06/13 Python
对Python中小整数对象池和大整数对象池的使用详解
2019/07/09 Python
windows、linux下打包Python3程序详细方法
2020/03/17 Python
Python爬取微信小程序Charles实现过程图解
2020/09/29 Python
BrandAlley英国:法国折扣奢侈品网上零售商
2017/07/03 全球购物
加拿大的标志性百货公司:Hudson’s Bay(哈得逊湾)
2019/09/03 全球购物
什么是Assembly(程序集)
2014/09/14 面试题
感谢信的格式
2015/01/21 职场文书
坎儿井导游词
2015/02/09 职场文书
给老婆的保证书怎么写
2015/05/08 职场文书
大学自主招生自荐信(2016精选篇)
2016/01/28 职场文书
java中重写父类方法加不加@Override详解
2021/06/21 Java/Android
分析Python list操作为什么会错误
2021/11/17 Python