Angular学习笔记

angular 的优点

  • 组织化前端结构
  • 强大和新颖
  • 完整的解决方案(路由、HTTP、RxJS等)
  • 构建强大单页应用
  • MVC设计模式
  • Tyepscript
  • 极好的cli工具

预备知识

  • Typescript
  • Classes
  • 高阶函数 - forEach、map、filter
  • 箭头函数
  • Promise
  • MVC设计模式

the angular way

  • 使用Typescript(变量、函数、参数)
  • 基于组件component based
  • 使用service来共享组件间的数据/功能
  • modules的概念(root module, forms modules, http module, etc)
  • 使用RxJS的observables来异步操作。(使用内置的HTTP模块发送请求,在组件中订阅返回的Observables)
  • 较陡的学习曲线

angular 基本用法

创建项目

ng new myapp

启动项目

ng serve

打包项目

ng build

创建组件

ng generate component todos

创建服务

ng generate service todo

创建模块

ng generate module 

在Angular的大型应用中可以使用ngrxRedux等状态管理工具

项目准备

安装angular
sudo npm install -g @angular/cli
验证安装
ng --version
新建项目
ng new todolist
运行项目
ng serve --open

index.html

单页应用入口,可以在这个文件中引入CDN,是组件的根标签

angular.json

项目配置文件,如打包目录(outputPath),静态资源目录(assets),样式目录(styles)

app.module.ts

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    AppRoutingModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

Angular中所有module必须导入后才能使用,如果使用cli创建模块,会自动进行导入

  • imports 使其他模块的导出声明在当前模块中可用

  • declarations 使当前模块中的指令(包括组件和管道)可用于当前模块中的其他指令

  • providers依赖注入知道servicesvalue,它们添加到root scope,并且注入到依赖它们的服务或指令

  • bootstrap数组声明哪些组件需要插入到index.html

将多个组件插入到index.html

index.html



test.component.ts

import { Component } from "@angular/core";

@Component({
  selector: "test-root",
  templateUrl: "./app.component.html",
  styleUrls: ["./app.component.css"],
})
export class TestComponent {
  title = "test";
}

app.module.ts

// ...
import { TestComponent } from "./test.component";
@NgModule({
  declarations: [AppComponent, TestComponent],
  imports: [BrowserModule, AppRoutingModule],
  providers: [],
  bootstrap: [AppComponent, TestComponent],
})
export class AppModule {}

基础语法

创建组件
ng generate component components/Todos
ng g c components/TodoItem
// 创建服务
ng g s services/Todo

该命令会在components文件夹下创建新的组件

属性绑定

[属性名]="属性值"

app/components/todo-item/todo-item.component.html

{{ todo.title }}

*ngFor循环语句

app/components/todos/todos.component.html

 
向子组件传参

[参数名]="参数值"向子组件传值

app/components/todos/todos.component.html

 

[todo]="todo"app-todo-item组件传值

接收参数

app/components/todo-item/todo-item.component.ts

export class TodoItemComponent implements OnInit {
  @Input() todo: Todo;
}

在模板中使用参数

app/components/todo-item/todo-item.component.html

{{ todo.title }}

向父组件传参

app/components/todo-item/todo-item.component.ts

import { Component, OnInit, Input, EventEmitter, Output } from "@angular/core";
import { Todo } from "../../models/Todo";
import { TodoService } from "../../services/todo.service";
@Component({
  selector: "app-todo-item",
  templateUrl: "./todo-item.component.html",
  styleUrls: ["./todo-item.component.css"],
})
export class TodoItemComponent implements OnInit {
  // 从父组件接收参数
  @Input() todo: Todo;
  // 向父组件传递参数
  @Output() deleteTodo: EventEmitter = new EventEmitter();
  constructor(private todoService: TodoService) {}

  ngOnInit(): void {}
  setClasses() {
    let classes = {
      todo: true,
      "is-completed": this.todo.completed,
    };
    return classes;
  }

  // onToggle
  onToggle(todo) {
    // Toggle on UI
    todo.completed = !todo.completed;
    // Toggle on server
    this.todoService.toggleCompleted(todo).subscribe((todo) => {
      console.log(todo);
    });
  }
  // 通过 emit 向父组件传参
  onDelete(todo) {
    this.deleteTodo.emit(todo);
  }
}

app/components/todos/todos.component.html



(deleteTodo)监听这个事件的名称和子组件的EventEmitter对象名必须一致

ngClass动态添加类

在HTML元素上添加或者移除CSS类

app/components/todo-item/todo-item.component.html

其中setClasses()是脚本文件中的一个方法

app/components/todo-item/todo-item.component.ts

export class TodoItemComponent implements OnInit {
  @Input() todo: Todo;
  constructor() {}

  ngOnInit(): void {}
  setClasses() {
    let classes = {
      todo: true,
      "is-completed": this.todo.completed,
    };
    return classes;
  }
}
监听事件

app/components/todo-item/todo-item.component.html

{{ todo.title }}

(change)监听输入框改变事件,(click)监听元素点击事件

网络请求

导入HTTP请求模块

app.module.ts

import { HttpClientModule } from "@angular/common/http";
@NgModule({
  declarations: [AppComponent, TodosComponent, TodoItemComponent],
  imports: [BrowserModule, AppRoutingModule, HttpClientModule],
  providers: [],
  bootstrap: [AppComponent],
})
export class AppModule {}

services发送请求

app/services/todo.service.ts

import { Injectable } from "@angular/core";
import { HttpClient, HttpHeaders } from "@angular/common/http";
import { Todo } from "../models/Todo";
import { Observable } from "rxjs";
@Injectable({
  providedIn: "root",
})
export class TodoService {
  todoUrl: string = "https://jsonplaceholder.typicode.com/todos?_limit=5";
  constructor(private http: HttpClient) {}
  getTodos(): Observable {
    return this.http.get(this.todoUrl);
  }
}
表单

导入表单模块

app.module.ts

import { FormsModule } from "@angular/forms";

@NgModule({
  declarations: [
    AppComponent,
    TodosComponent,
    TodoItemComponent,
    HeaderComponent,
    AddTodoComponent,
  ],

  imports: [BrowserModule, AppRoutingModule, HttpClientModule, FormsModule],
  providers: [],
  bootstrap: [AppComponent],
})
export class AppModule {}

在表单元素中使用双向数据绑定

app/components/add-todo/add-todo.component.html

{{ title }}

[(ngModel)]用于双向数据绑定

(ngSubmit)监听表单提交事件

监听表单提交事件

app/components/add-todo/add-todo.component.ts

import { Component, OnInit, Output, EventEmitter } from "@angular/core";

@Component({
  selector: "app-add-todo",
  templateUrl: "./add-todo.component.html",
  styleUrls: ["./add-todo.component.css"],
})
export class AddTodoComponent implements OnInit {
  title: string;
  @Output() addTodo: EventEmitter = new EventEmitter();

  constructor() {}

  ngOnInit(): void {}
  onSubmit() {
    const todo = {
      title: this.title,
      completed: false,
    };
    // 触发 addTodo 事件
    this.addTodo.emit(todo);
  }
}

表单提交事件处理

**app/components/todos/todos.component.html **




app/services/todo.service.ts

import { Injectable } from "@angular/core";
import { HttpClient, HttpHeaders } from "@angular/common/http";
import { Todo } from "../models/Todo";
import { Observable } from "rxjs";
const httpOptions = {
  headers: new HttpHeaders({
    "Content-Type": "application/json",
  }),
};
@Injectable({
  providedIn: "root",
})
export class TodoService {
  todoUrl: string = "https://jsonplaceholder.typicode.com/todos";
  todoLimit = "?_limit=5";

  constructor(private http: HttpClient) {}
  getTodos(): Observable {
    return this.http.get(`${this.todoUrl}${this.todoLimit}`);
  }
  // Toggle Completed
  // 发送json类型数据必须带请求头
  toggleCompleted(todo: Todo): Observable {
    const url = `${this.todoUrl}/${todo.id}`;
    return this.http.put(url, todo, httpOptions);
  }
  deleteTodo(todo: Todo): Observable {
    const url = `${this.todoUrl}/${todo.id}`;
    return this.http.delete(url, httpOptions);
  }
  addTodo(todo: Todo): Observable {
    return this.http.post(this.todoUrl, todo, httpOptions);
  }
}
路由

app/app-routing.module.ts

import { NgModule } from "@angular/core";
import { Routes, RouterModule } from "@angular/router";
import { TodosComponent } from "./components/todos/todos.component";
import { AboutComponent } from "./components/about/about.component";
const routes: Routes = [
  {
    path: "",
    component: TodosComponent,
  },
  {
    path: "about",
    component: AboutComponent,
  },
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule],
})
export class AppRoutingModule {}

app/app.component.html




路由跳转

app/components/layout/header/header.component.html

TODO

Home About

你可能感兴趣的:(Angular学习笔记)