技术背景:angular + ant zorro

最为大型前端团队首选的前端技术框架,angular,在国内多少还是有些水土不服。本人将针对angular做个一系列的填坑分享。

坑一:sdk

angular的sdk不属于各个模块,直接挂载在body下面, ant design直接使用sdk,导致任何的弹出层,如select,dropdown,picker等在弹出来的时候自动创建覆盖全局的sdk,需要点击sdk才能关闭已打开的下拉。

明显需要点击两次才能出现一个下拉是产品们不能接受的。

解决方案有两个,一个是修改底层源码,抛弃sdk,明显成本巨大,而且bug会层出不穷,考虑不周全,建议缺少前端架构组的团队就不用考虑了。

本人选择了另外一个方案,有点取巧,但是能快速解决问题。

 

步奏一:

将sdk缩小至1x1px,让鼠标可以点击网页中任意地方。

  1. .cdk-overlay-backdrop {
  2. width: 1px!important;
  3. height: 1px!important;
  4. }

步奏二:监听document点击事件

  1. document.addEventListener('click', (e) => {
  2. this.prepareHideModal(e);
  3. });

步奏三:获取当前点击的select等的唯一标识

使用sdk的组件比较多,有的有唯一标识,没有的特殊处理

  1. getSign(e) {
  2. for (const v of e['path']) {
  3. if (v.tagName == 'NZ-SELECT' || v.tagName == 'APP-SUBJECTPICKER') {
  4. // 下拉框获取sign
  5. if (v.classList[0].includes('ng-tns-')) {
  6. this.sign = v.classList[0];
  7. } else {
  8. this.sign = v.classList[1];
  9. }
  10. this.signType = 'NZ-NORMAL';
  11. break;
  12. } else if (v.tagName == 'NZ-PICKER') {
  13. // picker 获取sign
  14. this.sign = v.classList[0];
  15. this.signType = 'NZ-PICKER';
  16. break;
  17. }
  18. // popover 获取sign
  19. if (v.getAttributeNode && v.getAttributeNode('nz-popover') && v.getAttribute('nz-popover') == '') {
  20. this.sign = 'NZ-POPOVER';
  21. this.signType = 'NZ-POPOVER';
  22. break;
  23. }
  24. }
  25. }

步奏四:关闭已打开的下拉组件

为什么叫prepareHideModal,这是获取sign前的操作,先关闭再去获取点击下拉的sign

getSign方法在关闭后执行

  1. prepareHideModal(e) {
  2. let doClose = true;
  3. if (window['globalSignType']) {
  4. this.hideAllmodal();
  5. window['globalSignType'] = null;
  6. return;
  7. }
  8. // 如果有sign,关闭已打开的
  9. if (this.sign) {
  10. let _sign = this.sign;
  11. // 判断某些情况下不关闭弹框
  12. if (_sign == 'NZ-POPOVER') {
  13. // 解决没有特使标识时点击cdk本身不消失
  14. for (const v of e['path']) {
  15. if (v.classList && v.classList.contains('cdk-overlay-container')) {
  16. doClose = false;
  17. }
  18. }
  19. } else {
  20. // 常规有指定sign时点击选择器自身时不消失
  21. for (const v of e['path']) {
  22. if (v.classList && v.classList.contains(_sign)) {
  23. doClose = false;
  24. break;
  25. }
  26.  
  27. }
  28. }
  29. doClose && this.hideModal(_sign);
  30. }
  31. this.getSign(e);
  32. }

步奏五:最重要的关闭sdk,这边采用了最简单的,模拟sdk点击,完全使用sdk自己的方法

  1. hideModal(sign) {
  2. let cdkDom = document.querySelectorAll('.cdk-overlay-backdrop.cdk-overlay-dark-backdrop.cdk-overlay-backdrop-showing');
  3. let domLen = cdkDom.length;
  4. // 循环cdk,找到它自身的cdk,模拟点击隐藏
  5. for (var i = 0; i < domLen; i++) {
  6. var v = cdkDom[i];
  7. if (v['style'].display != 'none') {
  8. v['click']();
  9. break;
  10. }
  11. }
  12. this.sign = null;
  13. this.signType = null;
  14. }

至此算是解决了使用skd组件需要点击两次的坑,但是会引起另外一个坑,当页面出现滚动条时,已打开的下来组件位置不会跟着滚动而去改变。这边会在另外一篇博客中解决

 

版权声明:本文为wangmiao2606原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/wangmiao2606/p/10179287.html