1.[Angular 组件库 NG-ZORRO 基础入门] - 源码初窥: core
2.angular如何集成monaco-editor
3.angular8ï¼
4.ng-zorro-antd中踩过的坑
[Angular 组件库 NG-ZORRO 基础入门] - 源码初窥: core
在探索和了解了典型组件的源码之后,我们进一步深入 NG-ZORRO 组件库的核心结构,发现了一个关键的策略来解决组件间共用属性、功能导致的重复编写问题。NG-ZORRO 支持近 种组件,为避免每种组件都需要重复定义相同的主力支撑位源码属性或功能,开发团队采用了将公共方法和定义抽离至 `core` 文件夹的策略。
当处理组件的通用属性时,我们发现像 `nzSize` 这样的属性在多个组件如 `Input` 和 `Button` 中被广泛使用。解决这一问题的方法在于引入 `types` 文件夹,这个文件夹记录了哪些组件支持特定属性,便于我们查询和重复利用。
动画效果是layui的admin源码 Angular 开发中常见的元素,Angular 官方文档提供了详尽的指南。NG-ZORRO 提供了多样化的动画,使页面元素呈现丰富的动态变化。例如在 `Collapse` 折叠面板组件中,通过 `nzActive` 属性操控动画状态,实现元素的展开与收起效果。这一功能在实际开发中非常实用,使用动画使页面交互更加直观。
某些组件,如 `Tag`,在其动态删除操作中应用了淡入淡出动画,该动画机制相较于需要单独配置的肇源码头拍照状态传递更为简便,直接提升视觉效果和用户体验。NG-ZORRO 内含多种动画类型,如 `moveUpMotion` 和 `slideMotion`,通过探索源码可以轻易找到使用方式。
对于不希望使用动画的场景,NG-ZORRO 提供了 `NzNoAnimationDirective`,允许开发者在模板层面对特定元素禁用动画效果。通过替换 `BrowserAnimationsModule` 为 `NoopAnimationsModule`,可实现全局禁用动画。
总结这一系列核心文件夹——`core` 包含了如 `types` 和 `animations` 等内容,对于项目开发而言,应考虑抽离公共部分,指标源码龙头出局实现跨组件复用,以减少代码冗余和提高开发效率。通过借鉴 NG-ZORRO 的实践,开发者可以优化代码结构,提升组件复用性,同时保持代码的简洁性和易维护性。
angular如何集成monaco-editor
在进行前端开发时,如果需要集成高级代码编辑器,monaco-editor是一个理想的选择。本文将分享如何在Angular环境中成功集成monaco-editor,并解释其背后的原理和不同集成方式。基础配置
通常,宝贝手游源码第三方库通过npm安装并导入即可使用。然而,monaco-editor因其动态加载模块支持多种语言的特性,需要特殊处理。monaco-editor提供AMD和ESM两种包格式,它们的区别如下:AMD:异步加载模块标准,适合浏览器和异步加载场景,用define和require实现,可能需要额外的RequireJS库支持。
ESM:ECMAScript模块标准,静态加载,import和export操作,现代浏览器和Node.js原生支持,无需额外库。
Angular集成
根据monaco-editor的包类型,Angular的集成方式分为两种:AMD方式:在angular.json中配置资源路径,通过service管理模块加载。可以使用@monaco-editor/loader简化这一过程,它能从CDN获取或配置为本地资源。
ESM方式:使用webpack进行配置,推荐使用@angular-builders/custom-webpack或ngx-build-plus,官方提供了monaco-editor-webpack-plugin,但个人建议避免直接操作webpack配置。
另一种选择是使用封装好的组件库,如nz-zorro-antd的实验性code editor组件,它内含monaco-editor的实现,无需自己编写代码,可以直接查看其源码。总结
本文分享了将monaco-editor融入Angular项目的详细步骤,无论是AMD还是ESM方式,都涉及了必要的配置和最佳实践。希望这些信息对您的项目集成有所帮助。angular8ï¼
angular8项ç®å¤ç¯å¢é ç½®æ¹æ¡
项ç®å¨æå åå¸çæ¶åå¾å¾éè¦é ç½®ä¸åçserverçå°åï¼å½ç¶ï¼æäºåå¦ç¨çæ¯nginx转åï¼å æ¤ä¸éè¦ã
ä½ä¸ä» ä» å±éäºè¯·æ±å°åï¼æå¯è½æäºåéå¯é¥ççï¼æ¯å¦å¾®ä¿¡çappidï¼æµè¯ç¯å¢åæ£å¼ç¯å¢ç¨çå¯è½æ¯ä¸ä¸è´çã
为äºæ¹ä¾¿æå ï¼angularå·¥ç¨åä¸ä¸ºå¼åè åäºä¸äºæ¹è¿ãæå æ¶åï¼å¼å ¥environmentç设计ã
注æä¸ä¸å ç¹ï¼
1environmentsä¸å¯ä»¥é ç½®å¤å¥ä¸åçç¯å¢
2é»è®¤å¼å ¥çé½æ¯environment.tsï¼è¿ä¸ç¹å¿ é¡»ä¸è´çè ¢ã
3ä¿®æ¹angular.json
4æå æå®åæ°----configuration=dev
jsonä¸çprojects-项ç®å-architect-build-configurations-productionãå¢å ä¸åçç¯å¢é ç½®ï¼å¤å¶æ¯è¾å®¹æãngbuild--prod-c=devï¼
ç¶å设置jsonä¸çprojects-项ç®å-architect-serveï¼è¿æå°éªæ ·å°±å¯ä»¥å¨ngserveä¸å¢å æ´å¤çå°ºæºç¯å¢é ç½®ï¼ngserve-c=dev
æ¯ä¸æ¯å¾ç®åå¢ï¼æä»»ä½é®é¢å°±å¨ä¸é¢çè¨å§ï¼
Angular8å¼å ¥ngx-echartsæ¶æ¥éCannotreadproperty'init'ofnull
å¨é¡¹ç®ä¸ä½¿ç¨ngx-echartsæ¶éå°äºé®é¢ï¼å¨æ¬å°ç¯å¢ä¸ææçå¾åè½æ¾ç¤ºåºæ¥æ¸æ¯ï¼å¨æå åææçå¾åæ æ³æ¾ç¤ºå¹¶æ¥é
å¨æ¥çäºæºç ååç°é®é¢åºå¨echartsä¸ï¼echarts为null导ä¸éæ´è´äºè¯¥é®é¢çåºç°ã
èµ·åæ以为åå æ¯åºå¨çå½å¨æé©åä¸ï¼å°è¯·æ±æ°æ®çæ¹æ³åå¨äºngAfterViewInitå ï¼è¯¥é®é¢ä»ç¶æ²¡æå¾å°è§£å³ã
ç»è¿æ¥æ¾ç¸å ³èµæï¼å¨ngx-echartsçgitåºissueä¸æ¾å°äºè¯¥é®é¢ç解å³æ¹æ³ï¼
å¨è¿å²æ¨¡éçechartsåå¢å { init:echats.init}ï¼å³å¯è§£å³echartsæ¾ä¸å°çé®é¢ã
éä¸å®æ¹issueçå°åï¼
Angular8èµ·æ¥æç¨è¿å°±æ¯è¿ä¸ªç¤ºä¾æç¨çæç»ææã
ä¸é¢ä¸ä¸ªå¯¼èªæ¡ï¼ç¶åæ¯2个页é¢ã
å建å®æåï¼è¿è¡ï¼
æå¼/src/app/app.component.htmlï¼å é¤å 容ï¼æ·»å ï¼
æå¼/app/styles.scssï¼æ·»å ï¼
å建2个ç»ä»¶ï¼
æå¼/src/app/app-routing.module.tsæ·»å ï¼
æå¼/src/app/home/home.component.htmlï¼æ¿æ¢å 容为ï¼
home.component.tsä¸æ·»å ï¼
home.component.scssä¸æ·»å ï¼
home.component.htmlä¸æ·»å ï¼
/src/app/app.module.tsä¸æ·»å ï¼
home.component.tsä¸å®ä¹nameå±æ§ï¼
home.component.htmlä¸æ·»å ï¼
[ngIf]ç»å®ä¸ä¸ªè¡¨è¾¾å¼*clickCounter4*ã
å¦æ表达å¼ä¸ºfalseï¼å°ä¼è°ç¨ngIfElseæå®çå为noneç模æ¿ã
å¦æ表达å¼ä¸ºtrueï¼å°ä¼æ¾ç¤ºng-templateåä¸çHTMLå 容ã
æå¼home.component.htmlï¼ä¿®æ¹æåä¸ä¸ªplay-containerclassï¼
clickCounter4ä¹åï¼èæ¯è²å°±ä¼å为é»è²ã
è¿å¯ä»¥æå®å¤ä¸ªCSSå±æ§ï¼
å¦æä½ æ³æ·»å æè 移é¤å®ä¹å¨CSSä¸çclassï¼å¯ä»¥ä½¿ç¨classç»å®ã
ä¿®æ¹é¢¤éªå½åplay-containerï¼
home.component.scssä¸æ·»å ï¼
å¯ä»¥ä½¿ç¨ngClass设置å¤ä¸ªclassï¼
home.component.tsä¸æ·»å ï¼
home.component.scssä¸æ·»å ï¼
Serviceå¯ä»¥å¤ç¨ï¼æ¥ä¸æ¥æ们å建ä¸ä¸ªserviceï¼ç¨æ¥è°ç¨apiè·åæ°æ®ï¼å¹¶æ¾ç¤ºå¨list页é¢ã
gsæ¯generateserviceç缩åãèå¯è ¢
æ们ç»è¿ä¸ªserviceå½å为ponent.tsä¸æ·»å è°ç¨myMethodï¼
ngOnInit()ä¼å¨ç»ä»¶å è½½æ¶è§¦åã
ponent.tsä¸æ·»å ï¼
list.component.htmlä¸æ·»å ï¼
list.component.scssä¸æ·»å ï¼
æç»ææï¼
è®°å½angular8ä¸ä½¿ç¨inputæ¡è¾å ¥æ¯ä¸ä¸ªå符é½ä¼å¤±å»ç¦ç¹é®é¢å端æ¡æ¶angular8.0
uiç»ä»¶NG-ZORRO
åºæ¯ï¼è¡¨åè¾å ¥:å端å¨ææ·»å inputæ¡
æ°æ®ï¼egï¼['','','xxx']æ°ç»æ¯é¡¹ä¸ºstringç±»åï¼?["..1./",".2.1.",".2.1.-..1.
div?*ngFor="letitemofipPoolData['_ipAddress']indexasi;trackBy:trackByFn"?style="height:px;position:relative;"
inputname="{ { '_ipAddress'+i}}"nz-inputtype="text"placeholder="请è¾å ¥IP/åç½IP/åç½èå´"required[(ngModel)]="ipPoolData['_ipAddress'][i]"(ngModelChange)="checkIpRangeVal($event)"
span*ngIf="error['iprange']"class="text-error"IPè¾å ¥ä¸åæ³/spandivclass="btn-handle-item"buttonnz-buttonnzType="danger"[nzSize]="'small'"
(click)="deleteIPCollectionField(i)"*ngIf="ipPoolData['_ipAddress'].length1"
inz-iconnzType="minus"nzTheme="outline"/i
/button
button*ngIf="itemipPoolData['_ipAddress'].length5"
nz-buttonnzType="æºåé¦primary"[nzSize]="'small'"[disabled]="ipPoolData['_ipAddress'].length-1i"(click)="addIPCollectionField()"
inz-iconnzType="plus"nzTheme="outline"/i
/button
/div/div
å1ï¼
é®é¢ï¼?å½æ°ç»æ¯é¡¹ä¸ºstringç±»åæ¶ï¼å¾ªç¯åinputå ngmodelç´æ¥ç¨itemç»å®ï¼ä¼åºç°ngmodleæ æ³èµå¼é®é¢
解å³ï¼æ°ç»ngfor循ç¯åæ¯é¡¹å 容ngmodelç»å®éè ä»ç¨ipPoolData['_ipAdress'][i]ï¼è¥ç´æ¥ç¨itemåæ æ³ç»å®é¹æ°æ°æ®ï¼ngmodelä¸è¬éè¦item.valueç±»åï¼
å2ï¼
é®é¢ï¼inputæ¯è¾å ¥ä¸ä¸ªå符ï¼é¼ æ å°±ä¼å¤±ç¦é®é¢ï¼
åå ï¼ngmodelç¨ipPoolData['_ipAdress'][i]ç»å®åï¼inputæ¯æ¬¡è¾å ¥åï¼angularä¼éæ°æ¥è¯¢æå¡å¨å¯è½ä¼éç½®å å«æææ°æ¡ç®å¯¹è±¡çå表ï¼å³ä½¿å åå·²æ¾ç¤ºè¿äºæ¡ç®ä¹æ¯å¦æ¤ï¼å¨è¿ç§æ åµä¸ï¼Angularåªè½çå°ç±æ°ç对象å¼ç¨ç»æçæ°å表ï¼å®å«æ éæ©ï¼åªè½ç¨æææ°çDOMå ç´ æ¿æ¢æ§çDOMå ç´ ãå æ¤ä¼åºç°inputæ¯è¾å ¥ä¸ä¸ªå符ï¼é¼ æ å°±ä¼å¤±ç¦é®é¢ï¼
解å³æ¹æ¡ï¼
div*ngFor="letitemofipPoolData['_ipAddress']indexasi;trackBy:trackByFn"/div
ngFor循ç¯å使ç¨trackByï¼trackByFnï¼å该ç»ä»¶æ·»å ä¸ä¸ªæ¹æ³ï¼è¯¥æ¹æ³è¿åNgForåºè¯¥è·è¸ªçå¼ãè¿ä¸ªä¾åä¸ï¼è¯¥å¼æ¯ipPoolData['_ipAdress']çi项ï¼å¦æipPoolData['_ipAdress']çindex项已ç»è¢«æ¸²æï¼Angularå°±ä¼è·è¸ªå®ï¼èä¸ä¼éæ°åæå¡å¨æ¥è¯¢ç¸åçipPoolData['_ipAdress']çindex项ã
trackByFn(index:any,item:any){
returnindex;?}
angular8å¦ä¹ æ»ç»checkedRowIndex=-1;
checkedRowData:any;
pageInfo:PageInfoCompanyModalModel=newPageInfoCompanyModalModel();
orgName:string;
constructor(
privatemodal:ModalHelper,
privatecompanyConfig2Service:CompanyConfig2Service,
){ }
ngOnInit(){
this.getCompany();
}
select(data,i){
this.checkedRowChange(true,data,i);
}
getCompany(){
this.pageInfo.loading=true;
this.companyConfig2Service.getCompany({ pageInfo:{ pageNum:this.pageInfo.pageNum,pageSize:this.pageInfo.pageSize},orgName:this.orgName}).subscribe(data={
if(data){
this.pageInfo=data.data;
}
this.pageInfo.loading=false;
});
}
/
**/
**checkedRowChange(event,data,index){
this.checkedRowIndex=event?index:-1;
this.checkedRowData=data;
}
Angular8å®æï¼åä¸ï¼è½®æå¾ç»ä»¶æ¬ç« 主è¦å 容æ¯å®æè¿ä¸ªè½®æå¾ç»ä»¶~
ä½æ¯ä»ç¤ºä¾ä¸å¯ä»¥çåºï¼è½®æå°æåä¸å¼ å¾ä¹åå°±åæ¢äºï¼ä¸åæ»å¨äºãå¦ä½å¤çè¿ä¸ªé®é¢å¢ï¼ç®åçæ¹æ³æ¬ç©ºå°±æ¯ï¼åä½
åæ¥çä¸ä¸ææ
ä½æ¯æ¤æ¶å¦ææå¨åæ¢ï¼å¾çå¯è½ä¼äº®å¯çåå¨ä¸é´æé ãå¦ä½å¤çå¢?
æ·»å å¸éææçä¸ä¸
æ¤æ¶å¢ï¼è¿æä¸ä¸ªé®é¢ï¼å设ç®åå¨ç¬¬äºå¼ å¾çä¸ï¼å¦ææå¨å¾åæ»ä¸ä¸ï¼åºè¯¥è·³å第ä¸å¼ å¾çï¼ä½ç®åä¹ä¼ç´æ¥è·³å°ç¬¬ä¸å¼ å¾çãæ以æ们éè¦æ§å¶scrolläºä»¶ï¼åæ¶éè¦èèæ°ç»è¶ççå¤çã
6.indicator
indicatoråºè¯¥éçå¾ççè½®æä¹ä¼è½¬æ¢ï¼å¹¶ä¸æ们å¸æå¨å½åç´¢å¼æ¶ï¼indicatoræ¯çº¢è²çã
7.æåå¤çä¸ä¸å åæ³æ¼é®é¢
å½ä½¿ç¨setTimeoutï¼setIntervalçè¿äºæ¹æ³åï¼éè¦æ³¨æå åæ³æ¼çé®é¢ã
è³æ¤ï¼è½®æå¾å°±å ¨é¨å®æäºã
ng-zorro-antd中踩过的坑
在前端开发过程中,我们常常会借助阿里开源的组件库ant-design,它提供的组件功能强大,能满足大多数需求,直接使用即可,非常便捷。当然,一些公司会对此进行二次开发,以打造具有独特风格的产品。
本文将不涉及高深的技术细节,也不深入探讨底层源码,仅分享一些在项目中遇到的小问题。
表格(table)——师傅以为是组件库的bug,没想到……
不知道正在阅读本文的读者是否遇到过这样的情况:
这个空状态怎么总是和我们作对呢?为什么就不能满足我们的预期呢?其实,它偶尔也会满足我们的要求。
出现这种问题的原因实际上非常简单。回想一下,我们在删除和添加表项时,是否是这样操作的:
看起来这段代码没有问题,但要知道的是,push()和splice()这两个函数是直接在原始数组上操作的,会改变原数组。然而,它们会改变数组的引用吗?答案是:不会。
在angular的设计中,onChanges()监听的是哪种变化呢?是引用。
因此,只要我们改变引用地址,就可以解决这个问题。
这里提供的方法简单、快速、有效,非常实用。
读完本文,你是否有一种豁然开朗的感觉呢?