Angular入门笔记(超棒)web

【Angular本身对于状态的管理也是相当到位的,即使不使用redux,也可以做到跨组件共享数据,而且实现起来是非常容易的。】【在Angular框架中,它还深度继承了Rxjs,使得它处理异步编程的能力变得非常强大】

2、创建项目

import{Component}from"@angular/core"@Component({selector:"app-root",templateUrl:"./app.component.html",styleUrls:["./app.component.css"]})exportclassAppComponent{title="angular-test"}NgModule为组件提供了编译的上下文环境。

import{NgModule}from'@angular/core';import{AppComponent}from'./app.component';@NgModule({declarations:[AppComponent],bootstrap:[AppComponent]})exportclassAppModule{}关于Component有一个重要的点需要说明:组件必须是要属于一个NgModule的,也即是说NgModule为组件提供了编译的上下文环境,这也是Angular强制规定的,是Angular应用组织文件的一种方式。

服务用于放置和特定组件无关并希望跨组件共享的数据或逻辑。服务出现的目的在于解耦组件类中的代码,使组件类中的代码干净整洁。服务是由Injectable装饰器装饰的类。

import{Injectable}from'@angular/core';@Injectable({})exportclassAppService{}在使用服务时不需要在组件类中通过new的方式创建服务实例对象获取服务中提供的方法,以下写法错误,切记切记!!!

import{AppService}from"./AppService"exportclassAppComponent{letappService=newAppService()}可以想到的是:如果AppService的参数发生变化,那么使用到这个服务的所有地方,都需要进行修改,这不是我们想看到的结果。Angular中的依赖注入系统可以帮助我们改善这个局面。

服务的实例对象由Angular框架中内置的依赖注入系统创建和维护。服务是依赖需要被注入到组件中。

在组件中需要通过constructor构造函数的参数来获取服务的实例对象。

涉及参数就需要考虑参数的顺序问题,因为在Angular应用中会有很多服务,一个组件又不可能会使用到所有服务,如果组件要使用到最后一个服务实例对象,难道要将前面的所有参数都写上吗这显然不合理。

在组件中获取服务实例对象要结合TypeScript类型,写法如下。

import{AppService}from"./AppService"exportclassAppComponent{constructor(privateappService:AppService){}}为什么在形参前面加上private修饰符呢?appService只能在组件类当中使用,不能在组件模板中使用。

Angular会根据你指定的服务的类型来传递你想要使用的服务实例对象,这样就解决了参数的顺序问题。在Angular中服务被设计为单例模式,这也正是为什么服务可以被用来在组件之间共享数据和逻辑的原因。

第一种方式

npminit@angularproject-namecdproject-namenpmstart第二种方式

//enableProdMode方法调用后将会开启生产模式import{enableProdMode}from"@angular/core"//Angular应用程序的启动在不同的平台上是不一样的//在浏览器中启动时需要用到platformBrowserDynamic方法,该方法返回平台实例对象import{platformBrowserDynamic}from"@angular/platform-browser-dynamic"//引入根模块用于启动应用程序import{AppModule}from"./app/app.module"//引入环境变量对象{production:false}import{environment}from"./environments/environment"//如果当前为生产环境if(environment.production){//开启生产模式enableProdMode()}//启动应用程序platformBrowserDynamic().bootstrapModule(AppModule).catch(err=>console.error(err))

共享模块当中放置的是Angular应用中模块级别的需要共享的组件或逻辑。

@NgModule({declarations:[LayoutComponent],exports:[LayoutComponent]})exportclassSharedModule{}@NgModule({declarations:[AppComponent],imports:[SharedModule],bootstrap:[AppComponent]})exportclassAppModule{}@Component({selector:"app-root",template:`

Appworks
`,styles:[]})exportclassAppComponent{}在A模块中引入另一个B模块,那么就可以直接使用B模块中的组件和内容了;这种方式就可以不用在A模块中依次去引入B模块中的那些组件了。

数据绑定就是将组件类中的数据显示在组件模板中,当组件类中的数据发生变化时会自动被同步到组件模板中(数据驱动DOM)。

在Angular中使用插值表达式进行数据绑定,即双大括号语法{{}},也称大胡子语法。

{{message}}

{{getInfo()}}

{{a==b'相等':'不等'}}

{{'HelloAngular'}}

在插值语法中,不能使用ifelse语法;如果要显示字符串,需要用引号来包裹内容,否则它会认为这里是变量,是动态值。

属性绑定分为两种情况:绑定DOM对象属性和绑定HTML标记属性。

在大多数情况下,DOM对象属性和HTML标记属性是对应的关系,所以使用第一种情况。但是某些属性只有HTML标记存在,DOM对象中不存在,此时需要使用第二种情况:前面加上attr.,比如colspan属性,在DOM对象中就没有,或者自定义HTML属性也需要使用第二种情况。

homeworks!

import{AfterViewInit,ElementRef,ViewChild}from"@angular/core"exportclassHomeComponentimplementsAfterViewInit{@ViewChild("paragraph")paragraph:ElementRef|undefinedngAfterViewInit(){console.log(this.paragraph.nativeElement)}}使用ViewChildren获取一组元素

    abc
import{AfterViewInit,QueryList,ViewChildren}from"@angular/core"@Component({selector:"app-home",templateUrl:"./home.component.html",styles:[]})exportclassHomeComponentimplementsAfterViewInit{@ViewChildren("items")items:QueryList|undefinedngAfterViewInit(){console.log(this.items.toArray())}}这里需要注意的是:使用toArray方法来解析QueryList对象。

数据在组件类和组件模板中双向同步。Angular将双向数据绑定功能放在了@angular/forms模块中,所以要实现双向数据绑定需要依赖该模块。

Heading

Body
如果只有一个ng-content,不需要select属性。

ng-content在浏览器中会被替代,如果不想要这个额外的div,可以使用ng-container替代这个div。

属性指令:修改现有元素的外观或行为,使用[]包裹。

结构指令:增加、删除DOM节点以修改布局,使用*作为指令前缀。

根据条件渲染DOM节点或移除DOM节点。它返回的结果是一个布尔值。

课程列表0">没有更多数据*ngIf和hidden指令很像,但还是有区别的;*ngIf是渲染DOM节点或者移除DOM节点,也就是说*ngIf它有可能不渲染DOM节点,而hidden这个指令呢,无论如何,它是渲染这个DOM节点的,那么这个DOM节点的显示与隐藏呢,它是使用样式的方式(display)来控制的的。

遍历数据生成HTML结构

interfaceList{id:numbername:stringage:number}list:List[]=[{id:1,name:"张三",age:20},{id:2,name:"李四",age:30}]isEven:是否是基数行;isOdd:是否是偶数行。isFirst:是否是第一项;isLast:是否是最后一项。

//使用这种方式,Angular将使用trackByFn函数返回的唯一标识符来跟踪每个项目的变化,而不是使用对象引用。这可以提高性能,并减少不必要的DOM更新。identify(index,item){returnitem.id;}trackBy是一个可选的函数,用于提供一个唯一标识符来跟踪循环中的每个项目。使用trackBy函数有助于优化Angular的变更检测机制。当数组或集合发生变化时,Angular会通过比较新旧值来确定哪些项目已经被添加、删除或移动。如果没有提供trackBy函数,Angular默认会使用对象引用来进行比较,这可能导致不必要的DOM更新。

如何通过自定义指令来操作DOM

先来看一个需求:为元素设置默认背景颜色,鼠标移入时的背景颜色以及移出时的背景颜色。

HelloAngularimport{AfterViewInit,Directive,ElementRef,HostListener,Input}from"@angular/core"//接收参的数类型interfaceOptions{bgColor:string}@Directive({selector:"[appHover]"})exportclassHoverDirectiveimplementsAfterViewInit{//接收参数@Input("appHover")appHover:Options={}//要操作的DOM节点element:HTMLElement//获取要操作的DOM节点constructor(privateelementRef:ElementRef){this.element=this.elementRef.nativeElement}//组件模板初始完成后设置元素的背景颜色ngAfterViewInit(){this.element.style.backgroundColor=this.appHover.bgColor||"skyblue"}//为元素添加鼠标移入事件@HostListener("mouseenter")enter(){this.element.style.backgroundColor="pink"}//为元素添加鼠标移出事件@HostListener("mouseleave")leave(){this.element.style.backgroundColor="skyblue"}}在模板中使用appHover指令,默认状态是不加中括号的,当你需要传入动态数据的时候,那么你就需要加;@Directive({})中的selector定义的是指令的名称,class类中的@Input('appHover')是接受指令的参数。

像这样的间谍指令可以深入了解你无法直接修改的DOM对象。你无法触及内置

的实现,也无法修改第三方组件。但你有了一个选项来用指令监视这些元素。这个指令可以定义ngOnInit()和ngOnDestroy()钩子,它通过一个注入进来的LoggerService把消息记录到父组件中去。

管道的作用是用来处理组件模板当中数据的格式(格式化组件模板数据)。

{{date|date:"yyyy-MM-dd"}}{{object|json}}

{{object|json}}
内置管道不止这些,还有其他的。可以在官网查看,使用方式都是一样的。

先来看一个需求:指定字符串不能超过规定的长度,如果超过了,就把多余的截取掉,并再后面加上...

import{Input}from'@angular/core';exportclassFavoriteComponent{@Input("is-Favorite")isFavorite:boolean=false}@Input()括号中接收的参数,就是你传入进来的参数名。

现在有一个需求:在子组件中通过点击按钮将数据传递给父组件

挂载阶段的生命周期函数只在挂载阶段执行一次,数据更新时不再执行。

Angular在实例化组件类时执行,可以用来接收Angular注入的服务实例对象。(我们建议也只在constructor中做这个操作,不建议做别的操作)

exportclassChildComponent{constructor(privatetest:TestService){console.log(this.test)//"test"}}在首次接收到输入属性值后执行,在此处可以执行请求操作。

exportclassChildComponentimplementsOnInit{@Input("name")name:string=""ngOnInit(){console.log(this.name)//"张三"}}当内容投影初始渲染完成后调用。

HelloAngular

exportclassChildComponentimplementsAfterContentInit{@ContentChild("box")box:ElementRef|undefinedngAfterContentInit(){console.log(this.box)//
HelloAngular
}}当组件视图渲染完成后调用。

changeexportclassAppComponent{name:string="张三";age:number=20change(){this.name="李四"this.age=30}}exportclassChildComponentimplementsOnChanges{@Input("name")name:string=""@Input("age")age:number=0ngOnChanges(changes:SimpleChanges){console.log("基本数据类型值变化可以被检测到")}}引用数据类型变化

classMailService{constructor(APIKEY){}}classEmailSender{mailService:MailServiceconstructor(){this.mailService=newMailService("APIKEY1234567890")}sendMail(mail){this.mailService.sendMail(mail)}}constemailSender=newEmailSender()emailSender.sendMail(mail)EmailSender类运行时要使用MailService类,EmailSender类依赖MailService类,MailService类是EmailSender类的依赖项。

以上写法的耦合度太高,代码并不健壮。如果MailService类改变了参数的传递方式,在EmailSender类中的写法也要跟着改变。

classEmailSender{mailService:MailServiceconstructor(mailService:MailService){this.mailService=mailService}}constmailService=newMailService("APIKEY1234567890")constemailSender=newEmailSender(mailService)在实例化EmailSender类时将它的依赖项通过constructor构造函数参数的形式注入到类的内部,这种写法就是依赖注入。

通过依赖注入降了代码之间的耦合度,增加了代码的可维护性。MailService类中代码的更改再也不会影响EmailSender类。

Angular有一套自己的DI框架,它将实现依赖注入的过程隐藏了,对于开发者来说只需使用很简单的代码就可以使用复杂的依赖注入功能。

在Angular的DI框架中有四个核心概念:

注入器负责创建服务类实例对象,并将服务类实例对象注入到需要的组件中。

服务实际上就是一个类,在这个类当中可以有一些共享的属性和方法,那么这些共享的属性和方法,我们通常是在组件类当中去使用的,在组件类当中我们要使用服务类当中的属性或者方法,我们需要得到服务类的实例对象,但是在组件类当中,我们并不需要通过new关键字来实例化这个服务类,在Angular这个框架当中,它有自己的依赖注入系统,我们可以让Angular的依赖注入系统帮我们去实例化这个服务类,让Angular的依赖注入系统帮我们把这个服务类的实例对象注入到组件类当中。

import{Injectable}from'@angular/core';@Injectable({providedIn:'root'})exportclassCarListService{}第一种方式,在定义服务的时候,就定义服务注入的模块:

import{Injectable}from'@angular/core';import{CarModule}from'./car.module';@Injectable({providedIn:CarModule,})exportclassCarListService{}第二种方式:

表单的控制逻辑写在组件模板中,适合简单的表单类型。

import{FormsModule}from"@angular/forms"@NgModule({imports:[FormsModule],})exportclassAppModule{}模板变量的名字是自定义的,这里写的是:#f;并将模板变量赋值为:ngForm,这个是固定的。

import{NgForm}from"@angular/forms"exportclassAppComponent{onSubmit(form:NgForm){console.log(form.value)}}如果不想在input外面多一层div,可以把div替换为ng-container。

exportclassAppComponent{onSubmit(form:NgForm){//查看表单整体是否验证通过(验证通过valid是true,验证没通过valid是false)console.log(form.valid)//invalid与valid正好相反console.log(form.invalid)}}提交在组件模板中显示表单项未通过时的错误信息。

给表单项input添加一个模板变量username;touched表示用户有没有让这个表单项获取过焦点,表示用户有没有操作过这个表单项;

请填写用户名不符合正则规则指定表单项未通过验证时的样式。

在模型驱动表单中,表单字段需要是FormControl类的实例,实例对象可以验证表单字段中的值,值是否被修改过等等

一组表单字段构成整个表单,整个表单需要是FormGroup类的实例,它可以对表单进行整体验证。

import{AbstractControl,ValidationErrors}from"@angular/forms"import{Observable}from"rxjs"exportclassNameValidators{staticshouldBeUnique(control:AbstractControl):Promise{returnnewPromise(resolve=>{if(control.value=="admin"){resolve({shouldBeUnique:true})}else{resolve(null)}})}}contactForm:FormGroup=newFormGroup({name:newFormControl("",[Validators.required],NameValidators.shouldBeUnique)})异步验证规则需要写在formControl的第三个参数,第二个参数是同步验证规则。

用户名重复正在检测姓名是否重复异步验证器有一个耗时等待的过程,有一个pending属性可以用来判断当前是否处在异步验证的过程中(结果还没返回)

是创建模型表单的快捷方式。

解决这个问题的方案之一就是使用路由懒加载:用户在首次加载这个应用的时候,他只去请求根模块,其他的模块,等到用户访问的时候再去加载,这就是懒加载。

路由懒加载是以模块为单位的。如何实现路由懒加载呢?如下:

路由守卫是用来保护路由组件的,当你去访问某一个路由组件的时候,可以先去经过这个路由守卫,如果路由守卫允许你去访问,你才可以访问,如果路由守卫不允许你访问,那么你就不能够访问。

检查用户是否可以访问某一个路由。

CanActivate为接口,路由守卫类要实现该接口,该接口规定类中需要有canActivate方法,方法决定是否允许访问目标路由。

路由可以应用多个守卫,所有守卫方法都允许,路由才被允许访问,有一个守卫方法不允许,则路由不允许被访问。

创建路由守卫:nggguardguards/auth

创建路由守卫:nggguardguards/admin注意:使用命令行创建路由守卫,选择CanActivateChild,需要将箭头移动到这个选项并且敲击空格确认选择。

这个路由守卫可以解决的一个问题是:在网速比较慢的情况下,用户直接进入到这个路由,看到的是一个空的路由组件,给用户的一个错觉就是这个页面出bug了,这样就不太好了,我们可以使用Resolve这个路由守卫来解决这个问题。

THE END
1.DOM节点类型文档对象模型(DOM)是 HTML 和XML 文档的编程接口。它为文档提供了一种结构化的表示方法,允许开发者通过脚本来访问文档的结构、样式和内容。在 DOM 中,每个元素、属性、文本块等都被视为一个节点,这些节点构成了 DOM 树。本文将详细介绍 DOM 中的不同节点类型。 https://blog.csdn.net/wjs2024/article/details/143871001
2.dom分为哪三个部分WebKit JavaScript Binding添加新DOM对象的三种方式 一.基础知识 首先WebKit IDL并非完全遵循Web IDL,只是借鉴使用.WebKit官网提供了一份说明(WebKitIDL),比如Web IDL称"operation”(操作), 而WebKitIDL称为"method"(方法), 另外Web IDL也不像WebKitIDL那样将属性和参数分开. 为JavaScript绑定对象,可以使用module来定义https://www.shuzhiduo.com/topic/dom%E5%88%86%E4%B8%BA%E5%93%AA%E4%B8%89%E4%B8%AA%E9%83%A8%E5%88%86/
3.javascript学习笔记(一)DOM基本操作基础知识js教程document.body.appendChild(text); Java免费学习笔记:立即学习 解锁Java 大师之旅:从入门到精通的终极指南java速学教程(入门到精通) java怎么学习?java怎么入门?java在哪学?java怎么学才快?不用担心,这里为大家提供了java速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦! 下载 https://m.php.cn/faq/20226.html
4.DOM的基础知识DOM的基础知识 什么是DOM DOM:Document Object Model 文档对象模型是W3C组织推荐的处理可扩展标记语言的标准编程接口 B:浏览器O:对象M:模型,W3C定义了一系列的DOM接口,通过这些DOM接口可以改变网页的内容,结构和样式 DOM的简介 DOM树: 如何获取页面元素 document文档对象提供了一系列的api方法,可以方便我们操作dom数https://www.pianshen.com/article/15402497208/
5.Go语言学习&求职路径(附Go语言书单)第1篇“Go语言入门”,介绍Go语言的基础语法,既使没有Go语言基础的读者也可以学习本书。 第2篇“Go Web基础入门”,包括3章:Go Web开发基础、接收和处理Go Web请求、用Go访问数据库。本篇能使读者快速掌握用Go语言进行Web开发的基础知识。 第3篇“Go Web高级应用”,包括4章:Go高级网络编程、Go文件处理、Go并发http://www.broadview.com.cn/article/420281
6.Vue快速入门学习笔记(更新ing)本笔记综合了视频狂神说的Vue快速上手和菜鸟教程、CSDN等博客文章,以及个人的一些学习见解与体会。 由于是为了团队需要而快速入门,HTML、CSS、JS、Vue等基础均不全,故本笔记仅供参考学习使用。Vue 的核心库只关注视图层,方便与第三方库或既有项目整合。https://m.nowcoder.com/discuss/353148469172969472
7.ElementUI入门笔记(个人向)Element UI入门笔记 将页面分割为一级菜单、二级菜单、导航栏三个部分; 使用npm下载安装,使用语句npm i element-ui -s; 布局组件 --:key用于为每一个下拉选项设置唯一的Key值,用于Vue的虚拟DOM的diff算法--><!--:label设置选项要显示的文本信息--><!--:value设置选项选中后给http://www.mzph.cn/web/52984.shtml
8.E023Web学习笔记JQuery(一):基础知识51CTO博客E023Web学习笔记-JQuery(一):基础知识 一、JQuery基础 1、概念 jQuery 是一个 JavaScript 库; jQuery 极大地简化了 JavaScript 编程; jQuery 很容易学习; 2、快速入门 使用步骤: 第一步:下载JQuery; https://jquery.com/download/ 1. 第二步:导入JQuery的JS文件(直接复制);https://blog.51cto.com/u_13272819/6079059
9.Vue笔记——node.js入门知识这个时候我们的node.js便出现了。我们一旦安装好node.js之后,如何下载和安装的问题就迎刃而解,这个时候我们只需要使用npm install相关命令,node.js就可以帮助我们自动安装脚手架。如果你对npm不了解的话,推荐一篇博客:Vue笔记——npm入门知识。 安装好脚手架之后,我们在项目中还有会使用到各种各样的插件和库,比如vuehttps://www.jianshu.com/p/141c891561ec
10.Vue2.0学习笔记(基础篇)Vue2.0学习笔记(基础篇) 标签: JavaScript Vue.js 收藏 前言 纠结了很久到底是学Vue还是React,然后发现有纠结那么久的时间,说不定一个已经入门了。于是先挑一个基于原生js的框架Vue开始吧(还有个主要原因是Vue的中文官网做的比较小清新,看起来舒服). 稍微学习了一下,感觉vue和angular1.0真的有很多相像的地方。https://www.imooc.com/article/16117
11.JavaScript高级程序设计(第3版)(豆瓣)本来主攻PHP的我,在工作过程中发现JS的知识也是很必须的,所以决定开始学JS,然后在2012.6.7号在亚马逊买了这本书,以为可以用于入门,没想到这么书还是有一定难度,看了大半个月,才有一些零零碎碎的感觉本来自己基础不牢,也没什么好说的,所以说这本书还真的不适合初 (展开) 4 1 9回应 > 更多书评 https://book.douban.com/subject/10546125/
12.超过1000本的计算机经典书籍个人笔记资料以及本人在《Python入门教材(中文)》 百度云链接 提取码:d90e 《Python数据处理》 百度云链接 提取码:yqvb 《Python网络编程基础》 百度云链接 提取码:neke 《Python学习手册(第4版)》 百度云链接 提取码:gsio 《Python正则表达式-深入浅出》 百度云链接 提取码:sw5p 《Python知识手册-V2.0.1》 百度云链接 提取码:98a6 https://github.com/dptr/CS-Books/