IT0018.Angular从零到一

IT0018.Angular从零到一

华章IT

王芃 编著

机械工业出版社

ISBN:978-7-111-56283-2


【有道云笔记】IT0018.Angular从零到一
https://note.youdao.com/s/3y72LM3N

目录:

第1章 初始 Angular

第2章 用 Form 表单做一个登录控件

第3章 建立一个待办事项应用

第4章 进化!将应用模块化

第5章 多用户版本应用

第6章 使用第三方样式库及模块优化

第7章 给组件带来活力

第8章 Rx -- 隐藏在 Angular 中的利剑

第9章 用 Redux 管理 Angular 应用


读书笔记:

第1章 初始Angular

时间:2023年12月07日

书里要求是node 6.x.x,npm 3.x.x

我的MAC MINI电脑上是node 20.10.0 , npm 10.2.3

到npm.taobao.org上安装cnpm命令,用npm命令install取的外国的地址,经常下载失败

安装 sudo cnpm install -g @angular/cli (和书中不一样,按angular.cn中文官网上的为准)


查看angular-cli版本:ng version (目前用的是17.1.3)


创建项目  ng new my-app


由于使用 ng new app-name 这个命令,来创建项目很慢,是由于它需要下载很多的依赖包。所以可以通过如下命令 可以解决。
在命令后面加上参数 --skip-install    如:ng new app-name  --skip-install   
--skip-instal 意思是跳过安装 依赖包的过程。
在项目创建完成后,使用 cnpm install 来安装依赖包。


运行项目  ng serve


创建login组件 ng g c login
使用组件
// app\login\login.component.ts
import { Component } from '@angular/core';
import { CommonModule } from '@angular/common';
import { RouterOutlet } from '@angular/router';
//引入组件
import { LoginComponent } from './login/login.component';

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [CommonModule, RouterOutlet,LoginComponent], //导入
  templateUrl: './app.component.html',
  styleUrl: './app.component.css'
})
export class AppComponent {
  title = '哈哈哈hello Angular呆呆呆';
}
//在app.component.html里用组件的标签<app-login></app-login>即可




第2章 用Form表单做一个登录控件


建立一个Service完成业务逻辑: src文件夹中建立 app\core文件夹,再运行cmd命令 ng g s core\auth



//src\app\core\auth.service.ts
import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root'
})
export class AuthService {

  constructor() { }

  loginWithCreadentials(username:string, password:string):boolean{
    console.log("传进来的",username,password);
    if(username=="niunan"){
      return true;
    }
    return false;
  }
}
配置依赖注入



// src\app\app.config.ts
import { ApplicationConfig } from '@angular/core';
import { provideRouter } from '@angular/router';

import { routes } from './app.routes';
import { provideClientHydration } from '@angular/platform-browser';
import { AuthService } from './core/auth.service';  //记得要引用

export const appConfig: ApplicationConfig = {
  providers: [provideRouter(routes), provideClientHydration(),
    {provide:"auth",useClass:AuthService} //依赖注入
  ]
};
双向数据绑定及自定义验证样式
// src\app\login\login.component.ts
import { Component, Inject } from '@angular/core'; 
import { AuthService } from '../core/auth.service';

import { FormsModule } from '@angular/forms';   //双向绑定需要引入这个
import { CommonModule } from '@angular/common';  //*ngIf指令需要引入这个
 
 
@Component({
  selector: 'app-login',
  standalone: true,
  imports: [FormsModule,CommonModule],
  templateUrl: './login.component.html',
  styleUrl: './login.component.css'
})
export class LoginComponent { 
  username="";
  password = "";
  phone="";
  qq="";
  constructor(@Inject("auth") private service:AuthService){  //依赖注入
  }
  //表单提交,感觉没用,因为始终要定义上面的username,password。。。等
  onSubmit(formValue:any){
    console.log("表单提交了,formValue:",formValue);
    console.log(`username:${this.username},password:${this.password},phone:${this.phone},qq:${this.qq}`)
 
  }
  //单纯点击按钮
  onClick(){
    console.log('单纯点击按钮');
    console.log(`username:${this.username},password:${this.password},phone:${this.phone},qq:${this.qq}`)
    this.service.loginWithCreadentials(this.username,this.password);
    var b= this.service.loginWithCreadentials(this.username,this.password);
    console.log("登录结果 :",b);
  }
}
<!--/ src\app\login\login.component.html-->
<form #formRef="ngForm" (ngSubmit)="onSubmit(formRef.value)">
    <fieldset ngModelGroup="login">
 
    <div>
    <input name="username" type="text" required #usernameRef="ngModel" [(ngModel)]="username" placeholder="用户名" placeholder="请输入用户名" >
    <div *ngIf="usernameRef.errors?.['required']">必填</div>
</div>
<div>
    <input name="password" type="password" required minlength="6" #passwordRef="ngModel" [(ngModel)]="password" placeholder="请输入密码" >
    <div *ngIf="passwordRef.errors?.['minlength']">密码最少6位</div> 
</div>
</fieldset>
<fieldset ngModelGroup="info">
    手机号<input type="text" name="phone" [(ngModel)]="phone" />
    QQ:<input type="text" name="qq" [(ngModel)]="qq" />
</fieldset>
    <button type="submit">登录</button>
    <button type="button" (click)="onClick()">点一下后看看Control</button>
    <hr />
    <div>
        username:{{username}},
        password:{{password}}
    </div>
</form>
/* src\app\login\login.component.css */

/*验证未通过文本框样式*/
input.ng-invalid{
    border:1px solid red;
}
/*验证通过文本框样式*/
input.ng-valid{
    border:1px solid green;
}



第3章 建立一个待办事项应用
第4章 进化!将应用模块化
第5章 多用户版本应用

第6章 使用第三方样式库及模块优化


发布项目命令:ng build --aot
发布后IIS里建立网站目录指向 disk/browser 即可
书里的样式库:https://getmdl.io/
网站上的是CSS的,书里的封装成组件了,用的是
真的主页及各组件的使用在
之前创建的是在angular 17下的项目,所以得用命令
cnpm install @angular-mdl/core --save
来安装MDL样式库
然后在index.html引入样式文件
<link rel="stylesheet" href="https://code.getmdl.io/1.1.3/material.indigo-pink.min.css"/>
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
以上都是可以在github上找到相关代码
然后在app.module.ts中import进来
// src\app\app.module.ts

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { LoginComponent } from './login/login.component';
import { routing } from './app.routes';
import { FormsModule} from '@angular/forms';
import { TodoComponent } from './todo/todo.component';
import { provideHttpClient } from '@angular/common/http';

 import { MdlModule } from '@angular-mdl/core';  //加入第三方样式库
@NgModule({
  declarations: [
    AppComponent,
    LoginComponent,
    TodoComponent
  ],
  imports: [
    BrowserModule,
    FormsModule, 
    AppRoutingModule,
    routing,
     MdlModule //加入第三方样式库
  ],
  providers: [provideHttpClient()],
  bootstrap: [AppComponent]
})
export class AppModule { }
在todo页面就可以直接使用了


<!-- src\app\todo\todo.component.html -->
<div style="padding:20px;">
<p>todo works!</p>
<p>
 
    <mdl-textfield [(ngModel)]="desc" floating-label label="小目标:" type="text" (keyup.enter)="addTodo()" ></mdl-textfield>
</p>
<mdl-list>
    <mdl-list-item  *ngFor="let todo of todos">
      <mdl-list-item-primary-content>
        <mdl-checkbox (change)="toggleTodo(todo)" [(ngModel)]="todo.completed" [mdl-ripple]="true">
            {{todo.id}}. {{todo.desc}}
          </mdl-checkbox>
      </mdl-list-item-primary-content>
      <mdl-list-item-secondary-action>
        <button mdl-button mdl-button-type="icon"  (click)="removeTodo(todo)" mdl-colored="accent">
            <mdl-icon>delete</mdl-icon>
          </button>
      </mdl-list-item-secondary-action>
    </mdl-list-item> 
  </mdl-list>
 

    <footer>
        <hr />
        共 {{todos.length}} 项待办
        <a href="">全部</a> |
        <a href="">未完成</a> |
        <a href="">已完成</a> 
    </footer>
 
</div>
效果图:



自己在测试的时候碰到如下问题:


ng serve 出错:listen EACCES: permission denied ::1:4200
解决:
管理员CMD下
net stop winnat
netsh int ipv4 set dynamic tcp start=49152 num=16384
netsh int ipv6 set dynamic tcp start=49152 num=16384
net start winnat
参考
https://superuser.com/questions/1437780/how-to-fix-listen-eacces-permission-denied-on-any-port



第7章 给组件带来活力
第8章 Rx ---- 隐藏在Angular中的利剑
第9章 用Redux管理Angular应用