1.[Angular 组件库 NG-ZORRO 基础入门] - 源码初窥: core
2.angular如何集成monaco-editor
3.angular8ï¼
4.ng-zorro-antd中踩过的坑
[Angular 组件库 NG-ZORRO 基础入门] - 源码初窥: core
在探索和了解了典型组件的源码之后,我们进一步深入 NG-ZORRO 组件库的核心结构,发现了一个关键的策略来解决组件间共用属性、功能导致的重复编写问题。NG-ZORRO 支持近 种组件,为避免每种组件都需要重复定义相同的手机读写nfc源码属性或功能,开发团队采用了将公共方法和定义抽离至 `core` 文件夹的策略。
当处理组件的通用属性时,我们发现像 `nzSize` 这样的属性在多个组件如 `Input` 和 `Button` 中被广泛使用。解决这一问题的方法在于引入 `types` 文件夹,这个文件夹记录了哪些组件支持特定属性,便于我们查询和重复利用。
动画效果是手机游戏官网源码 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()监听的是哪种变化呢?是引用。
因此,只要我们改变引用地址,就可以解决这个问题。
这里提供的方法简单、快速、有效,非常实用。
读完本文,你是否有一种豁然开朗的感觉呢?