在本系列的第1部分中,我们学习了如何启动并运行Todo应用程序并将其部署到GitHub页面。 这工作得很好,但不幸的是,整个应用程序都挤在一个组件中。 在本文中,我们将研究更模块化的组件体系结构。 我们将研究如何将单个组件分解为更易于理解,重用和维护的较小组件的结构化树。

本文是SitePoint Angular 2+教程的第2部分,有关如何使用Angular CLI创建CRUD应用程序。

  1. 第0部分— Ultimate Angular CLI参考指南
  2. 第1部分-启动并运行我们的Todo应用程序的第一个版本
  3. 第2部分-创建单独的组件以显示待办事项列表和一个待办事项
  4. 第3部分-更新Todo服务以与REST API通信
  5. 第4部分-使用Angular路由器解析数据 。
  6. 第5部分-添加身份验证以保护私有内容
  7. 第6部分-如何将Angular项目更新到最新版本。

并不需要遵循本教程的第一部分,对第二部分是有道理的。 您可以简单地获取一份我们的仓库的副本,从第一部分中检出代码,然后以此作为起点。 下面将对此进行详细说明。

角组件架构

快速回顾

因此,让我们更详细地看一下第一部分中介绍的内容。 我们学习了如何:

  • 使用Angular CLI初始化我们的Todo应用程序
  • 创建一个Todo类来代表单个Todo
  • 创建TodoDataService服务以创建,更新和删除待办事项
  • 使用AppComponent组件显示用户界面
  • 将我们的应用程序部署到GitHub页面。

第1部分的应用程序架构如下所示:

应用架构

我们讨论的组件标有红色边框。

在第二篇文章中,我们将把AppComponent所做的一些工作委托给更易于理解,重用和维护的较小组件。

我们将创建:

  • TodoListComponent以显示TodoListComponent列表
  • TodoListItemComponent以显示单个待办事项
  • 一个TodoListHeaderComponent来创建一个新的待办事项
  • TodoListFooterComponent来显示还剩下多少个TodoListFooterComponent

应用架构

到本文结尾,您将了解:

  • Angular组件架构的基础
  • 如何使用属性绑定将数据传递到组件中
  • 如何使用事件侦听器侦听组件发出的事件
  • 为什么将组件拆分为较小的可重用组件是一个好习惯
  • 智能组件和组件之间的区别以及为什么保持组件是一个好习惯。

因此,让我们开始吧!

启动并运行

您需要在本文中遵循的第一件事是Angular CLI的最新版本。 您可以使用以下命令进行安装:

npm install -g @angular/cli@latest

如果您需要删除以前版本的Angular CLI,请按以下步骤操作:

npm uninstall -g @angular/cli angular-cli
npm cache clean
npm install -g @angular/cli@latest

之后,您将需要第一部分的代码副本。 可从https://github.com/sitepoint-editors/angular-todo-app获得 。 本系列中的每篇文章在存储库中都有一个相应的标记,因此您可以在应用程序的不同状态之间来回切换。

我们在第一部分结尾和在本文开始的代码被标记为part-1 。 本文结尾处的代码被标记为part-2 。

您可以将标签视为特定提交ID的别名。 您可以使用git checkout在它们之间切换。 您可以在此处阅读更多内容 。

因此,要启动并运行(已安装Angular CLI的最新版本),我们将执行以下操作:

git clone git@github.com:sitepoint-editors/angular-todo-app.git
cd angular-todo-app
npm install
git checkout part-1
ng serve

然后访问http:// localhost:4200 / 。 如果一切顺利,您应该会看到正在运行的Todo应用程序。

原始AppComponent

让我们打开src/app/app.component.html并看一下我们在第一部分中完成的AppComponent

<section class="todoapp"><header class="header"><h1>Todos</h1><input class="new-todo" placeholder="What needs to be done?" autofocus="" [(ngModel)]="newTodo.title" (keyup.enter)="addTodo()"></header><section class="main" *ngIf="todos.length > 0"><ul class="todo-list"><li *ngFor="let todo of todos" [class.completed]="todo.complete"><div class="view"><input class="toggle" type="checkbox" (click)="toggleTodoComplete(todo)" [checked]="todo.complete"><label>{{todo.title}}</label><button class="destroy" (click)="removeTodo(todo)"></button></div></li></ul></section><footer class="footer" *ngIf="todos.length > 0"><span class="todo-count"><strong>{{todos.length}}</strong> {{todos.length == 1 ? 'item' : 'items'}} left</span></footer>
</section>

这是src/app/app.component.ts对应的类:

import {Component} from '@angular/core';
import {Todo} from './todo';
import {TodoDataService} from './todo-data.service';@Component({selector: 'app-root',templateUrl: './app.component.html',styleUrls: ['./app.component.css'],providers: [TodoDataService]
})
export class AppComponent {newTodo: Todo = new Todo();constructor(private todoDataService: TodoDataService) {}addTodo() {this.todoDataService.addTodo(this.newTodo);this.newTodo = new Todo();}toggleTodoComplete(todo: Todo) {this.todoDataService.toggleTodoComplete(todo);}removeTodo(todo: Todo) {this.todoDataService.deleteTodoById(todo.id);}get todos() {return this.todoDataService.getAllTodos();}}

尽管我们的AppComponent可以正常工作,但是将所有代码都保留在一个大组件中并不能很好地扩展,因此不建议这样做。

向我们的Todo应用程序添加更多功能将使AppComponent更大,更复杂,从而使其更难以理解和维护。

因此,建议将功能委派给较小的组件。 理想情况下,较小的组件应该是可配置的,以便在业务逻辑更改时我们不必重写其代码。

例如,在本系列的第三部分中,我们将更新TodoDataService以与REST API进行通信,并且我们希望确保在重构TodoDataService时不必更改任何较小的组件。

如果我们查看AppComponent模板,则可以将其基础结构提取为:

<!-- header that lets us create new todo -->
<header></header><!-- list that displays todos -->
<ul class="todo-list"><!-- list item that displays single todo --><li>Todo 1</li><!-- list item that displays single todo --><li>Todo 2</li>
</ul><!-- footer that displays statistics -->
<footer></footer>

如果将此结构转换为Angular组件名称,则会得到:

<!-- TodoListHeaderComponent that lets us create new todo -->
<app-todo-list-header></app-todo-list-header><!-- TodoListComponent that displays todos -->
<app-todo-list><!-- TodoListItemComponent that displays single todo --><app-todo-list-item></app-todo-list-item><!-- TodoListItemComponent that displays single todo --><app-todo-list-item></app-todo-list-item>
</app-todo-list><!-- TodoListFooterComponent that displays statistics -->
<app-todo-list-footer></app-todo-list-footer>

让我们看看如何利用Angular的组件驱动开发的力量来实现这一目标。

更具模块化的组件体系结构—创建TodoListHeaderComponent

让我们从创建TodoListHeader组件开始。

从项目的根源开始,我们使用Angular CLI为我们生成组件:

$ ng generate component todo-list-header

这会为我们生成以下文件:

create src/app/todo-list-header/todo-list-header.component.css
create src/app/todo-list-header/todo-list-header.component.html
create src/app/todo-list-header/todo-list-header.component.spec.ts
create src/app/todo-list-header/todo-list-header.component.ts

它将TodoListHeaderComponent自动添加到AppModule声明中:

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { HttpModule } from '@angular/http';import { AppComponent } from './app.component';// Automatically imported by Angular CLI
import { TodoListHeaderComponent } from './todo-list-header/todo-list-header.component';@NgModule({declarations: [AppComponent,// Automatically added by Angular CLITodoListHeaderComponent],imports: [BrowserModule,FormsModule,HttpModule],providers: [],bootstrap: [AppComponent]
})
export class AppModule { }

需要将组件添加到模块声明中,以确保模块中的所有视图模板都可以使用该组件。 Angular CLI方便TodoListHeaderComponent为我们添加了TodoListHeaderComponent ,因此我们不必手动添加它。

如果TodoListHeaderComponent不在声明中,而我们在视图模板中使用了它,Angular将抛出以下错误:

Error: Uncaught (in promise): Error: Template parse errors:
'app-todo-list-header' is not a known element:
1. If 'app-todo-list-header' is an Angular component, then verify that it is part of this module.
2. If 'app-todo-list-header' is a Web Component then add "CUSTOM_ELEMENTS_SCHEMA" to the '@NgModule.schemas' of this component to suppress this message.

要了解有关模块声明的更多信息,请务必查看Angular Module FAQ 。

现在我们已经为新的TodoListHeaderComponent生成了所有文件,我们可以将<header>元素从src/app/app.component.html移至src/app/todo-list-header/todo-list-header.component.html

<header class="header"><h1>Todos</h1><input class="new-todo" placeholder="What needs to be done?" autofocus="" [(ngModel)]="newTodo.title"(keyup.enter)="addTodo()">
</header>

还要将相应的逻辑添加到src/app/todo-list-header/todo-list-header.component.ts

import { Component, Output, EventEmitter } from '@angular/core';
import { Todo } from '../todo';@Component({selector: 'app-todo-list-header',templateUrl: './todo-list-header.component.html',styleUrls: ['./todo-list-header.component.css']
})
export class TodoListHeaderComponent {newTodo: Todo = new Todo();@Output()add: EventEmitter<Todo> = new EventEmitter();constructor() {}addTodo() {this.add.emit(this.newTodo);this.newTodo = new Todo();}}

相反,注入的TodoDataService在我们的新TodoListHeaderComponent保存新的待办事项,我们发出add事件,并通过新的todo作为参数。

我们已经了解到,Angular模板语法允许我们将处理程序附加到事件。 例如,考虑以下代码:

<input (keyup.enter)="addTodo()">

这告诉Angular在输入内部按下Enter键时运行addTodo()方法。 之所以keyup.enter ,是因为keyup.enter事件是Angular框架定义的事件。

但是,我们还可以通过创建EventEmitter并使用@Output()装饰器装饰组件,使组件发出自己的自定义事件:

import { Component, Output, EventEmitter } from '@angular/core';
import { Todo } from '../todo';@Component({// ...
})
export class TodoListHeaderComponent {// ...@Output()add: EventEmitter<Todo> = new EventEmitter();addTodo() {this.add.emit(this.newTodo);this.newTodo = new Todo();}}

因此,我们现在可以使用Angular的事件绑定语法在视图模板中分配事件处理程序:

<app-todo-list-header (add)="onAddTodo($event)"></app-todo-list-header>

每次我们在TodoListHeaderComponent调用add.emit(value)TodoListHeaderComponent调用add.emit(value) onAddTodo($event)处理函数,并且$event等于value

这将我们的TodoListHeaderComponentTodoDataService分离,并允许父组件决定在创建新的TodoDataService时需要做什么。

当我们在TodoDataService部分中更新TodoDataService与REST API通信时,我们不必担心TodoListHeaderComponent因为它甚至不知道TodoDataService存在。

智能与哑组件

您可能已经听说过智能哑巴组件 。 将TodoListHeaderComponentTodoDataService使TodoListHeaderComponent成为愚蠢的组件。 愚蠢的组件不知道外部发生了什么。 它仅通过属性绑定接收输入,并且仅将输出数据作为事件发出。

使用智能哑巴组件是一个好习惯。 它极大地改善了关注点的分离,使您的应用程序更易于理解和维护。 如果您的数据库或后端API发生了变化,则不必担心笨拙的组件。 它还使您的哑组件更加灵活,使您可以在不同情况下更轻松地重用它们。 如果您的应用程序需要两次相同的组件,一次需要将其写入后端数据库,而另一次需要将其写入内存数据库,那么哑巴组件可以使您准确地完成此任务。

现在,我们已经创建了TodoListHeaderComponent ,让我们更新AppComponent模板以使用它:

<section class="todoapp"><!-- header is now replaced with app-todo-list-header --><app-todo-list-header (add)="onAddTodo($event)"></app-todo-list-header><section class="main" *ngIf="todos.length > 0"><ul class="todo-list"><li *ngFor="let todo of todos" [class.completed]="todo.complete"><div class="view"><input class="toggle" type="checkbox" (click)="toggleTodoComplete(todo)" [checked]="todo.complete"><label>{{todo.title}}</label><button class="destroy" (click)="removeTodo(todo)"></button></div></li></ul></section><footer class="footer" *ngIf="todos.length > 0"><span class="todo-count"><strong>{{todos.length}}</strong> {{todos.length == 1 ? 'item' : 'items'}} left</span></footer></section>

请注意,当用户输入新的待办事项标题时,我们如何使用onAddTodo($event)处理程序捕获TodoListHeaderComponent发出的add事件:

<app-todo-list-header (add)="onAddTodo($event)"></app-todo-list-header>

我们将onAddTodo()处理函数添加到AppComponent类中,并删除不再需要的逻辑:

import {Component} from '@angular/core';
import {Todo} from './todo';
import {TodoDataService} from './todo-data.service';@Component({selector: 'app-root',templateUrl: './app.component.html',styleUrls: ['./app.component.css'],providers: [TodoDataService]
})
export class AppComponent {// No longer needed, now handled by TodoListHeaderComponent// newTodo: Todo = new Todo();constructor(private todoDataService: TodoDataService) {}// No longer needed, now handled by TodoListHeaderComponent// addTodo() {//   this.todoDataService.addTodo(this.newTodo);//   this.newTodo = new Todo();// }// Add new method to handle event emitted by TodoListHeaderComponentonAddTodo(todo: Todo) {this.todoDataService.addTodo(todo);}toggleTodoComplete(todo: Todo) {this.todoDataService.toggleTodoComplete(todo);}removeTodo(todo: Todo) {this.todoDataService.deleteTodoById(todo.id);}get todos() {return this.todoDataService.getAllTodos();}}

现在,我们已成功地将<header>元素和所有基础逻辑从AppComponent移至其自己的TodoListHeaderComponent

TodoListHeaderComponent是一个愚蠢的组件, AppComponent仍然负责使用TodoDataService存储待办事项。

接下来,让我们解决TodoListComponent

创建TodoListComponent

让我们再次使用Angular CLI生成我们的TodoListComponent

$ ng generate component todo-list

这会为我们生成以下文件:

create src/app/todo-list/todo-list.component.css
create src/app/todo-list/todo-list.component.html
create src/app/todo-list/todo-list.component.spec.ts
create src/app/todo-list/todo-list.component.ts

它还会自动将TodoListComponent添加到AppModule声明中:

// ...
import { TodoListComponent } from './todo-list/todo-list.component';@NgModule({declarations: [// ...TodoListComponent],// ...
})
export class AppModule { }

现在,我们从src/app/app.component.html获取与待办事项列表相关的HTML:

<section class="main" *ngIf="todos.length > 0"><ul class="todo-list"><li *ngFor="let todo of todos" [class.completed]="todo.complete"><div class="view"><input class="toggle" type="checkbox" (click)="toggleTodoComplete(todo)" [checked]="todo.complete"><label>{{todo.title}}</label><button class="destroy" (click)="removeTodo(todo)"></button></div></li></ul>
</section>

我们还将其移至src/app/todo-list/todo-list.component.html

<section class="main" *ngIf="todos.length > 0"><ul class="todo-list"><li *ngFor="let todo of todos" [class.completed]="todo.complete"><app-todo-list-item[todo]="todo"(toggleComplete)="onToggleTodoComplete($event)"(remove)="onRemoveTodo($event)"></app-todo-list-item></li></ul>
</section>

请注意,我们引入了尚不存在的TodoListItemComponent 。 但是,将其添加到模板中已经使我们能够探索TodoListItemComponent应该提供的API。 这使我们在TodoListItemComponent中编写TodoListItemComponent更加容易,因为我们现在知道我们期望TodoListItemComponent具有哪些输入和输出。

我们使用[todo] 输入属性语法通过todo属性传递todo项,并将事件处理程序附加到我们希望TodoListItemComponent发出的事件上,例如toggleComplete事件和remove事件。

让我们打开src/app/todo-list/todo-list.component.ts并添加视图模板所需的逻辑:

import { Component, EventEmitter, Input, Output } from '@angular/core';
import { Todo } from '../todo';@Component({selector: 'app-todo-list',templateUrl: './todo-list.component.html',styleUrls: ['./todo-list.component.css']
})
export class TodoListComponent {@Input()todos: Todo[];@Output()remove: EventEmitter<Todo> = new EventEmitter();@Output()toggleComplete: EventEmitter<Todo> = new EventEmitter();constructor() {}onToggleTodoComplete(todo: Todo) {this.toggleComplete.emit(todo);}onRemoveTodo(todo: Todo) {this.remove.emit(todo);}}

为了进一步说明智能组件和组件之间的区别,我们还将TodoListComponent 组件。

首先,我们通过使用@Input()装饰器将输入属性标记为todos来定义它。 这使我们能够从父组件中注入todos

接下来,我们使用@Output()装饰器定义两个输出事件, removetoggleComplete 。 请注意,我们如何将它们的类型设置为EventEmitter<Todo>并为它们分配一个新的EventEmitter实例。

EventEmitter<Todo>类型注释是TypeScript泛型 ,它告诉TypeScript removetoggleComplete都是EventEmitter实例,它们发出的值是Todo实例。

最后,我们使用(toggleComplete)="onToggleTodoComplete($event)"(remove)="onRemoveTodo($event)"定义在视图中指定的onToggleTodoComplete(todo)onRemoveTodo(todo)事件处理程序。

注意我们如何在视图模板中使用$event作为参数名称,并在方法定义中使用todo作为参数名称。 要访问Angular模板中事件的有效负载(发射值),我们必须始终使用$event作为参数名称。

因此,通过指定(toggleComplete)="onToggleTodoComplete($event)"在我们的视图模板,我们告诉角度使用事件负载作为第一个参数调用时onToggleTodoComplete方法,这将在第一个参数匹配onToggleTodoComplete方法,即todo

我们知道有效负载将是一个todo实例,因此我们将onToggleTodoComplete方法定义为onToggleTodoComplete(todo: Todo) ,这使我们的代码更易于阅读,理解和维护。

最后,我们定义事件处理程序以在接收到有效负载时也发出toggleCompleteremove事件,并将todo指定为事件有效负载。

本质上,我们让TodoListComponent对其子TodoListItemComponent实例中的事件进行TodoListItemComponent

这使我们能够处理TodoListComponent之外的业务逻辑,从而保持TodoListComponent 愚蠢 ,灵活和轻便。

我们还需要在AppComponent重命名两个方法来反映这一点:

...
export class AppComponent {// rename from toggleTodoCompleteonToggleTodoComplete(todo: Todo) {this.todoDataService.toggleTodoComplete(todo);}// rename from removeTodoonRemoveTodo(todo: Todo) {this.todoDataService.deleteTodoById(todo.id);}}

如果我们尝试在此阶段运行应用程序,Angular将抛出错误:

Unhandled Promise rejection: Template parse errors:
Can't bind to 'todo' since it isn't a known property of 'app-todo-list-item'.
1. If 'app-todo-list-item' is an Angular component and it has 'todo' input, then verify that it is part of this module.
2. If 'app-todo-list-item' is a Web Component then add "CUSTOM_ELEMENTS_SCHEMA" to the '@NgModule.schemas' of this component to suppress this message.

那是因为我们还没有创建TodoListItemComponent

因此,让我们接下来做。

创建TodoListItemComponent

同样,我们使用Angular CLI生成TodoListItemComponent

$ ng generate component todo-list-item

这将生成以下文件:

create src/app/todo-list-item/todo-list-item.component.css
create src/app/todo-list-item/todo-list-item.component.html
create src/app/todo-list-item/todo-list-item.component.spec.ts
create src/app/todo-list-item/todo-list-item.component.ts

它将TodoListItemComponent自动添加到AppModule声明中:

// ...
import { TodoListItemComponent } from './todo-list-item/todo-list-item.component';@NgModule({declarations: [// ...TodoListItemComponent],// ...
})
export class AppModule { }

现在,我们可以将原始标记从<li>内部移动到src/app/todo-list-item.component.html

<div class="view"><input class="toggle" type="checkbox" (click)="toggleTodoComplete(todo)" [checked]="todo.complete"><label>{{todo.title}}</label><button class="destroy" (click)="removeTodo(todo)"></button>
</div>

我们不必对标记进行任何更改,但是必须确保事件得到正确处理,因此让我们在src/app/todo-list-item/todo-list-item.component.ts添加必要的代码TodoListItemComponent src/app/todo-list-item/todo-list-item.component.ts

import { Component, Input, Output, EventEmitter } from '@angular/core';
import { Todo } from '../todo';@Component({selector: 'app-todo-list-item',templateUrl: './todo-list-item.component.html',styleUrls: ['./todo-list-item.component.css']
})
export class TodoListItemComponent {@Input() todo: Todo;@Output()remove: EventEmitter<Todo> = new EventEmitter();@Output()toggleComplete: EventEmitter<Todo> = new EventEmitter();constructor() {}toggleTodoComplete(todo: Todo) {this.toggleComplete.emit(todo);}removeTodo(todo: Todo) {this.remove.emit(todo);}}

该逻辑与TodoListComponent的逻辑非常相似。

首先我们定义一个@Input()以便我们可以传入一个Todo实例:

@Input() todo: Todo;

然后,我们为模板定义click事件处理程序,并在单击复选框时发出toggleComplete事件,在单击'X'时发出remove事件:

@Output()
remove: EventEmitter<Todo> = new EventEmitter();@Output()
toggleComplete: EventEmitter<Todo> = new EventEmitter();toggleTodoComplete(todo: Todo) {this.toggleComplete.emit(todo);
}removeTodo(todo: Todo) {this.remove.emit(todo);
}

请注意,我们实际上是如何不更新或删除数据的。 我们只是发出从事件TodoListItemComponent当用户点击一个链接,完成或删除待办事项,使得我们TodoListItemComponent也是一个愚蠢的组成部分。

记住我们如何将事件处理程序附加到TodoListComponent模板中的这些事件:

<section class="main" *ngIf="todos.length > 0"><ul class="todo-list"><li *ngFor="let todo of todos" [class.completed]="todo.complete"><app-todo-list-item[todo]="todo"(toggleComplete)="onToggleTodoComplete($event)"(remove)="onRemoveTodo($event)"></app-todo-list-item></li></ul>
</section>

然后, TodoListComponent只需从TodoListItemComponent重新发出事件。

冒泡从事件TodoListItemComponent通过TodoListComponent使我们能够保持两个组件 ,并确保我们没有更新他们的时候,我们重构TodoDataService在本系列的第三部分与REST API进行通信。

多么酷啊!

在继续之前,让我们更新AppComponent模板以使用新的TodoListComponent

<section class="todoapp"><app-todo-list-header (add)="onAddTodo($event)"></app-todo-list-header><!-- section is now replaced with app-todo-list --><app-todo-list [todos]="todos" (toggleComplete)="onToggleTodoComplete($event)"(remove)="onRemoveTodo($event)"></app-todo-list><footer class="footer" *ngIf="todos.length > 0"><span class="todo-count"><strong>{{todos.length}}</strong> {{todos.length == 1 ? 'item' : 'items'}} left</span></footer></section>

最后,让我们解决TodoListFooterComponent

创建TodoListFooterComponent

同样,从项目的根源开始,我们使用Angular CLI为我们生成TodoListFooterComponent

$ ng generate component todo-list-footer

这将生成以下文件:

create src/app/todo-list-footer/todo-list-footer.component.css
create src/app/todo-list-footer/todo-list-footer.component.html
create src/app/todo-list-footer/todo-list-footer.component.spec.ts
create src/app/todo-list-footer/todo-list-footer.component.ts

它将TodoListFooterComponent自动添加到AppModule声明中:

// ...
import { TodoListFooterComponent } from './todo-list-footer/todo-list-footer.component';@NgModule({declarations: [// ...TodoListFooterComponent],// ...
})
export class AppModule { }

现在,将<footer>元素从src/app/app.component.htmlsrc/app/todo-list-footer/todo-list-footer.component.html

<footer class="footer" *ngIf="todos.length > 0"><span class="todo-count"><strong>{{todos.length}}</strong> {{todos.length == 1 ? 'item' : 'items'}} left</span>
</footer>

我们还将相应的逻辑添加到src/app/todo-list-footer/todo-list-footer.component.ts

import { Component, Input } from '@angular/core';
import { Todo } from '../todo';@Component({selector: 'app-todo-list-footer',templateUrl: './todo-list-footer.component.html',styleUrls: ['./todo-list-footer.component.css']
})
export class TodoListFooterComponent {@Input()todos: Todo[];constructor() {}}

TodoListFooterComponent不需要任何方法。 我们仅使用@Input()装饰器定义todos属性,因此我们可以使用todos属性传入todos

最后,让我们更新AppComponent模板,使其也使用新的TodoListFooterComponent

<section class="todoapp"><app-todo-list-header (add)="onAddTodo($event)"></app-todo-list-header><app-todo-list [todos]="todos" (toggleComplete)="onToggleTodoComplete($event)"(remove)="onRemoveTodo($event)"></app-todo-list><app-todo-list-footer [todos]="todos"></app-todo-list-footer>
</section>

现在,我们已经成功地重构了AppComponent以将其功能委托给TodoListHeaderComponentTodoListComponentTodoListFooterComponent

在总结本文之前,我们还需要进行一些更改。

移动TodoDataService提供程序

在第一部分,我们注册了TodoDataService作为一个供应商AppComponent

import {Component} from '@angular/core';
import {Todo} from './todo';
import {TodoDataService} from './todo-data.service';@Component({selector: 'app-root',templateUrl: './app.component.html',styleUrls: ['./app.component.css'],providers: [TodoDataService]
})
export class AppComponent {newTodo: Todo = new Todo();constructor(private todoDataService: TodoDataService) {}addTodo() {this.todoDataService.addTodo(this.newTodo);this.newTodo = new Todo();}toggleTodoComplete(todo: Todo) {this.todoDataService.toggleTodoComplete(todo);}removeTodo(todo: Todo) {this.todoDataService.deleteTodoById(todo.id);}get todos() {return this.todoDataService.getAllTodos();}}

尽管这对于我们的Todo应用程序来说效果很好,但是Angular团队建议将应用程序范围的提供程序添加到根AppModule而不是根AppComponent

AppComponent中注册的服务仅可用于AppComponent及其组件树。 在AppModule中注册的服务可用于整个应用程序中的所有组件。

如果我们的Todo应用程序会增长并在某个时候引入延迟加载的模块,则延迟加载的模块将无法访问TodoDataService ,因为TodoDataService仅可用于AppComponent及其组件树,而不能在整个应用程序中使用。

因此,我们删除TodoDataService作为一个供应商AppComponent

import {Component} from '@angular/core';
import {Todo} from './todo';
import {TodoDataService} from './todo-data.service';@Component({selector: 'app-root',templateUrl: './app.component.html',styleUrls: ['./app.component.css'],providers: []
})
export class AppComponent {newTodo: Todo = new Todo();constructor(private todoDataService: TodoDataService) {}addTodo() {this.todoDataService.addTodo(this.newTodo);this.newTodo = new Todo();}toggleTodoComplete(todo: Todo) {this.todoDataService.toggleTodoComplete(todo);}removeTodo(todo: Todo) {this.todoDataService.deleteTodoById(todo.id);}get todos() {return this.todoDataService.getAllTodos();}}

接下来,将其添加为AppModule的提供者:

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { HttpModule } from '@angular/http';import { AppComponent } from './app.component';
import { TodoDataService } from './todo-data.service';
import { TodoListComponent } from './todo-list/todo-list.component';
import { TodoListFooterComponent } from './todo-list-footer/todo-list-footer.component';
import { TodoListHeaderComponent } from './todo-list-header/todo-list-header.component';
import { TodoListItemComponent } from './todo-list-item/todo-list-item.component';@NgModule({declarations: [AppComponent,TodoListComponent,TodoListFooterComponent,TodoListHeaderComponent,TodoListItemComponent],imports: [BrowserModule,FormsModule,HttpModule],providers: [TodoDataService],bootstrap: [AppComponent]
})
export class AppModule { }

到此结束本系列的第二部分。

摘要

在第一篇文章中 ,我们学习了如何:

  • 使用Angular CLI初始化我们的Todo应用程序
  • 创建一个Todo类来代表单个Todo
  • 创建TodoDataService服务以创建,更新和删除待办事项
  • 使用AppComponent组件显示用户界面
  • 将我们的应用程序部署到GitHub页面。

在第二篇文章中,我们重构了AppComponent ,将其大部分工作委托给:

  • TodoListComponent以显示TodoListComponent列表
  • TodoListItemComponent以显示单个待办事项
  • 一个TodoListHeaderComponent来创建一个新的待办事项
  • TodoListFooterComponent来显示还剩下多少个TodoListFooterComponent

在此过程中,我们了解到:

  • Angular组件架构的基础
  • 如何使用属性绑定将数据传递到组件中
  • 如何使用事件侦听器侦听组件发出的事件
  • 如何将组件拆分为较小的可重用组件,从而使我们的代码更易于重用和维护
  • 当我们需要重构应用程序的业务逻辑时,如何使用智能哑巴来简化我们的生活。

这篇文章中的所有代码都可以从https://github.com/sitepoint-editors/angular-todo-app获得 。

在下一部分中,我们将重构TodoService以与REST API通信。

因此,请继续关注第三部分!


本文由Vildan Softic进行同行评审。 感谢所有SitePoint的同行评审人员使SitePoint内容达到最佳状态!

对于专家主导的在线Angular培训课程,您不能超越Todd Motto的Ultimate Angular。 在这里尝试他的课程 ,并使用代码SITEPOINT_SPECIAL获得50%的折扣并帮助支持SitePoint。

From: https://www.sitepoint.com/understanding-component-architecture-angular/

查看全文
如若内容造成侵权/违法违规/事实不符,请联系编程学习网邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!

相关文章

  1. AngularJS进阶(六)AngularJS+BootStrap实现弹出对话框

    分享一下我老师大神的人工智能教程&#xff01;零基础&#xff0c;通俗易懂&#xff01;http://blog.csdn.net/jiangjunshow也欢迎大家转载本篇文章。分享知识&#xff0c;造福人民&#xff0c;实现我们中华民族伟大复兴&#xff01;AngularJSBootStrap实现弹出对话框参考资料&…...

    2024/4/26 5:39:52
  2. Angular 4官方文档(一)【架构】

    初识 Angular 之&#xff08;一&#xff09;架构 Angular 是一个构建客户端应用的框架。它使用 HTML 和 JavaScript 或者可以被编译成 JavaScript&#xff08;比如 TypeScript&#xff09; 的语言。 Angular 框架由多个库文件(libraries)组成。其中&#xff0c; 有些是核心库…...

    2024/4/21 3:57:05
  3. Promise的前世今生和妙用技巧

    浏览器事件模型和回调机制 JavaScript作为单线程运行于浏览器之中&#xff0c;这是每本JavaScript教科书中都会被提到的。同时出于对UI线程操作的安全性考虑&#xff0c;JavaScript和UI线程也处于同一个线程中。因此对于长时间的耗时操作&#xff0c;将会阻塞UI的响应。为了更好…...

    2024/4/21 3:57:04
  4. Angular vs React:谁更适合前端开发

    翻译原文地址&#xff1a;http://www.tuicool.com/articles/Jb6bmuz 原文地址&#xff1a;http://https://juejin.im/post/59ab51746fb9a024865d202b Angular vs React&#xff1a;谁更适合前端开发 大家总在写文章争论&#xff0c;Angular 与 React 哪一个才是前端开发的更好…...

    2024/4/21 3:57:02
  5. angular案例--电话簿

    项目二 0 效果展示 在这里插入图片描述 一 项目初始化 1.搭建项目 ng new 项目名(等到开始出现进度条的时候打断) cd 项目目录(进入你刚创建的项目中) cnpm install(安装需要用的包等) npm start(启动项目)2. 初始化组件 //组件的划分与页面相关 cd 项目目录 ng g compon…...

    2024/4/21 3:57:02
  6. 用angular做表单验证

    先上图 看到红色箭头所示&#xff0c;有注意两点&#xff1a; 当文本框获得焦点的时候&#xff0c;有一个box-shadow的效果同时会有验证 都知道input是单标签&#xff08;不闭合&#xff09;的元素&#xff0c;为了实现这个效果&#xff0c;就需要用到div将input包围起来&…...

    2024/4/20 7:50:31
  7. angular 表单验证之ngMessages

    之所以要写这篇文章&#xff0c;是因为要纠正《Angular 权威教程 》这本书中的关于ngMessage中的写法错误。对于ngMessages这个插件的用法其实还是比较容易的。但比较坑爹的是学习这块最开始的参照教程就是这本书&#xff0c;它里面的写法又是错误的。百度查找了一些国人写的文…...

    2024/4/22 18:07:36
  8. springmvc入门helloword(springmvc教程一)

    目录spring mvc核心流程图与实际代码关联入门工程搭建 spring mvc核心流程图与实际代码关联入门工程搭建 业务层只有一个controller层 文件结构pom.xml <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-in…...

    2024/5/6 5:45:47
  9. angular js 指令

    Angular 指令 ng-app 指令 ng-app 指令定义了 AngularJS 应用程序的 根元素。 ng-app 指令在网页加载完毕时会自动引导&#xff08;自动初始化&#xff09;应用程序。 稍后您将学习到 ng-app 如何通过一个值&#xff08;比如 ng-app"myModule"&#xff09;连接到代码…...

    2024/4/21 3:56:57
  10. Angular 4.x 自定义验证指令

    表单是几乎每个 Web 应用程序的一部分。虽然 Angular 为我们提供了几个内置 validators (验证器)&#xff0c;但在实际工作中为了满足项目需求&#xff0c;我们经常需要为应用添加一些自定义验证功能。接下来我们将着重介绍&#xff0c;如何自定义 validator 指令。 Built-in V…...

    2024/4/21 3:56:56
  11. Angular JS验证

    常用的表单验证指令 1. 必填项验证 某个表单输入是否已填写&#xff0c;只要在输入字段元素上添加HTML5标记required即可&#xff1a; <input type"text" required /> 2. 最小长度验证表单输入的文本长度是否大于某个最小值&#xff0c;在输入字段上使用指令n…...

    2024/4/20 4:47:37
  12. Angular2 指令

    1. 指令说明 Angular2 指令是构成Angular2应用程序的重要组成部分&#xff0c;指令主要用来对模板的标签或者元素附加一些新的特性或者功能&#xff0c;改变一个 DOM 元素的外观或行为&#xff0c;Angular2指令和组件十分类似&#xff0c;也有由模块&#xff0c;注解&#xff0…...

    2024/5/4 23:55:45
  13. 简单的angular表单验证指令

    <html ng-app"myApp"><head><meta charset"UTF-8"><title>test表单验证</title><script type"text/javascript" src"lib/angular/angular.js"></script><script type"text/javascr…...

    2024/4/21 7:15:30
  14. angular表单验证及 提交功能实现

    本例通过Angular框架来实现简单的表单验证 一、html结构 1、借助于bootstrap快速的编写了一个简单的表单 代码主要部分如下&#xff1a; <div class"container" style"margin-top: 30px;" ng-controller"myCtrl"><h1 style"text…...

    2024/4/20 19:58:09
  15. 表单常用的angular指令

    ng-model 指令根据表单域的状态添加/移除以下类&#xff1a; 1.input为为空的时候ng-empty 2.input不为空的时候ng-not-empty 3.控件已失去焦点ng-touched 4.控件未失去焦点的时候ng-untouched 5.验证通过ng-valid 6.验证失败ng-invalid 7.控件输入值已变更ng-dirty 8.ng-prist…...

    2024/5/3 17:43:25
  16. angular在线验证用户名是否唯一 指令

    <input name"username" type"text" class"form-control" id"username" placeholder"用户名" ensure-unique"username" required ng-model"info.username">.directive(ensureUnique, function($ht…...

    2024/4/23 18:13:48
  17. angular表单密码验证自定义指令

    html <form name"form"><input type"password" name"password" ng-model"password" required placeholder"请输入密码"><input type"password" name"passwordConfirm" ng-model"pa…...

    2024/4/20 19:58:05
  18. 【Angular2】搭建开发环境

    一、前言 随着前端工程化的浪潮到来&#xff0c;最近公司的新项目需要使用Angular2作为前端的开发语言。当然小编之前是没有接触的&#xff0c;而且Angular2也是在AngularJs的基础上发展出来的。但是官网说他们相同的地方不多&#xff0c;事实证明确实不多。但是经过小编几个月…...

    2024/4/21 3:56:53
  19. Angular 开发环境配置方式

    配置开发环境 本快速入门教程&#xff0c;选用第一种配置方式搭建 Angular 开发环境&#xff1a; 基于 Angular Quickstart 使用 Git 克隆 quickstart 项目 git clone https://github.com/angular/quickstart ng4-quickstart 使用 IDE 打开已新建的项目 (本教程使用的 IDE 是 V…...

    2024/4/21 3:56:51
  20. Angular开发环境搭建和项目创建以及启动

    工具的安装 首先需要安装node&#xff0c;直接在官网下载node&#xff0c;然后一直下一步安装完即可&#xff0c;在安装node的时候自带了npm包管理工具 然后安装Angular CLI&#xff0c;使用npm命令安装输入以下命令 npm install -g angular/cli 使用ng -v 查看版本是多少&…...

    2024/4/21 3:56:50

最新文章

  1. 如何在您的WordPress网站上安装和设置Yoast seo?

    本周有一个客户&#xff0c;购买Hostease的虚拟主机&#xff0c;询问我们的在线客服&#xff0c;如何在您的WordPress网站上安装和设置Yoast seo?我们为用户提供相关教程&#xff0c;用户很快解决了遇到的问题。在此&#xff0c;我们分享这个操作教程&#xff0c;希望可以对您…...

    2024/5/9 19:01:33
  2. 梯度消失和梯度爆炸的一些处理方法

    在这里是记录一下梯度消失或梯度爆炸的一些处理技巧。全当学习总结了如有错误还请留言&#xff0c;在此感激不尽。 权重和梯度的更新公式如下&#xff1a; w w − η ⋅ ∇ w w w - \eta \cdot \nabla w ww−η⋅∇w 个人通俗的理解梯度消失就是网络模型在反向求导的时候出…...

    2024/5/7 10:36:02
  3. JRT高效率开发

    得益于前期的基础投入&#xff0c;借助代码生成的加持&#xff0c;本来计划用一周实现质控物维护界面&#xff0c;实际用来四小时左右完成质控物维护主体&#xff0c;效率大大超过预期。 JRT从设计之初就是为了证明Spring打包模式不适合软件服务模式&#xff0c;觉得Spring打包…...

    2024/5/9 17:21:26
  4. [C++][算法基础]模拟队列(数组)

    实现一个队列&#xff0c;队列初始为空&#xff0c;支持四种操作&#xff1a; push x – 向队尾插入一个数 x&#xff1b;pop – 从队头弹出一个数&#xff1b;empty – 判断队列是否为空&#xff1b;query – 查询队头元素。 现在要对队列进行 M 个操作&#xff0c;其中的每…...

    2024/5/9 17:15:21
  5. 【外汇早评】美通胀数据走低,美元调整

    原标题:【外汇早评】美通胀数据走低,美元调整昨日美国方面公布了新一期的核心PCE物价指数数据,同比增长1.6%,低于前值和预期值的1.7%,距离美联储的通胀目标2%继续走低,通胀压力较低,且此前美国一季度GDP初值中的消费部分下滑明显,因此市场对美联储后续更可能降息的政策…...

    2024/5/8 6:01:22
  6. 【原油贵金属周评】原油多头拥挤,价格调整

    原标题:【原油贵金属周评】原油多头拥挤,价格调整本周国际劳动节,我们喜迎四天假期,但是整个金融市场确实流动性充沛,大事频发,各个商品波动剧烈。美国方面,在本周四凌晨公布5月份的利率决议和新闻发布会,维持联邦基金利率在2.25%-2.50%不变,符合市场预期。同时美联储…...

    2024/5/9 15:10:32
  7. 【外汇周评】靓丽非农不及疲软通胀影响

    原标题:【外汇周评】靓丽非农不及疲软通胀影响在刚结束的周五,美国方面公布了新一期的非农就业数据,大幅好于前值和预期,新增就业重新回到20万以上。具体数据: 美国4月非农就业人口变动 26.3万人,预期 19万人,前值 19.6万人。 美国4月失业率 3.6%,预期 3.8%,前值 3…...

    2024/5/4 23:54:56
  8. 【原油贵金属早评】库存继续增加,油价收跌

    原标题:【原油贵金属早评】库存继续增加,油价收跌周三清晨公布美国当周API原油库存数据,上周原油库存增加281万桶至4.692亿桶,增幅超过预期的74.4万桶。且有消息人士称,沙特阿美据悉将于6月向亚洲炼油厂额外出售更多原油,印度炼油商预计将每日获得至多20万桶的额外原油供…...

    2024/5/9 4:20:59
  9. 【外汇早评】日本央行会议纪要不改日元强势

    原标题:【外汇早评】日本央行会议纪要不改日元强势近两日日元大幅走强与近期市场风险情绪上升,避险资金回流日元有关,也与前一段时间的美日贸易谈判给日本缓冲期,日本方面对汇率问题也避免继续贬值有关。虽然今日早间日本央行公布的利率会议纪要仍然是支持宽松政策,但这符…...

    2024/5/4 23:54:56
  10. 【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响

    原标题:【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响近日伊朗局势升温,导致市场担忧影响原油供给,油价试图反弹。此时OPEC表态稳定市场。据消息人士透露,沙特6月石油出口料将低于700万桶/日,沙特已经收到石油消费国提出的6月份扩大出口的“适度要求”,沙特将满…...

    2024/5/4 23:55:05
  11. 【外汇早评】美欲与伊朗重谈协议

    原标题:【外汇早评】美欲与伊朗重谈协议美国对伊朗的制裁遭到伊朗的抗议,昨日伊朗方面提出将部分退出伊核协议。而此行为又遭到欧洲方面对伊朗的谴责和警告,伊朗外长昨日回应称,欧洲国家履行它们的义务,伊核协议就能保证存续。据传闻伊朗的导弹已经对准了以色列和美国的航…...

    2024/5/4 23:54:56
  12. 【原油贵金属早评】波动率飙升,市场情绪动荡

    原标题:【原油贵金属早评】波动率飙升,市场情绪动荡因中美贸易谈判不安情绪影响,金融市场各资产品种出现明显的波动。随着美国与中方开启第十一轮谈判之际,美国按照既定计划向中国2000亿商品征收25%的关税,市场情绪有所平复,已经开始接受这一事实。虽然波动率-恐慌指数VI…...

    2024/5/7 11:36:39
  13. 【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试

    原标题:【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试美国和伊朗的局势继续升温,市场风险情绪上升,避险黄金有向上突破阻力的迹象。原油方面稍显平稳,近期美国和OPEC加大供给及市场需求回落的影响,伊朗局势并未推升油价走强。近期中美贸易谈判摩擦再度升级,美国对中…...

    2024/5/4 23:54:56
  14. 【原油贵金属早评】市场情绪继续恶化,黄金上破

    原标题:【原油贵金属早评】市场情绪继续恶化,黄金上破周初中国针对于美国加征关税的进行的反制措施引发市场情绪的大幅波动,人民币汇率出现大幅的贬值动能,金融市场受到非常明显的冲击。尤其是波动率起来之后,对于股市的表现尤其不安。隔夜美国股市出现明显的下行走势,这…...

    2024/5/6 1:40:42
  15. 【外汇早评】美伊僵持,风险情绪继续升温

    原标题:【外汇早评】美伊僵持,风险情绪继续升温昨日沙特两艘油轮再次发生爆炸事件,导致波斯湾局势进一步恶化,市场担忧美伊可能会出现摩擦生火,避险品种获得支撑,黄金和日元大幅走强。美指受中美贸易问题影响而在低位震荡。继5月12日,四艘商船在阿联酋领海附近的阿曼湾、…...

    2024/5/4 23:54:56
  16. 【原油贵金属早评】贸易冲突导致需求低迷,油价弱势

    原标题:【原油贵金属早评】贸易冲突导致需求低迷,油价弱势近日虽然伊朗局势升温,中东地区几起油船被袭击事件影响,但油价并未走高,而是出于调整结构中。由于市场预期局势失控的可能性较低,而中美贸易问题导致的全球经济衰退风险更大,需求会持续低迷,因此油价调整压力较…...

    2024/5/8 20:48:49
  17. 氧生福地 玩美北湖(上)——为时光守候两千年

    原标题:氧生福地 玩美北湖(上)——为时光守候两千年一次说走就走的旅行,只有一张高铁票的距离~ 所以,湖南郴州,我来了~ 从广州南站出发,一个半小时就到达郴州西站了。在动车上,同时改票的南风兄和我居然被分到了一个车厢,所以一路非常愉快地聊了过来。 挺好,最起…...

    2024/5/7 9:26:26
  18. 氧生福地 玩美北湖(中)——永春梯田里的美与鲜

    原标题:氧生福地 玩美北湖(中)——永春梯田里的美与鲜一觉醒来,因为大家太爱“美”照,在柳毅山庄去寻找龙女而错过了早餐时间。近十点,向导坏坏还是带着饥肠辘辘的我们去吃郴州最富有盛名的“鱼头粉”。说这是“十二分推荐”,到郴州必吃的美食之一。 哇塞!那个味美香甜…...

    2024/5/4 23:54:56
  19. 氧生福地 玩美北湖(下)——奔跑吧骚年!

    原标题:氧生福地 玩美北湖(下)——奔跑吧骚年!让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 啊……啊……啊 两…...

    2024/5/8 19:33:07
  20. 扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!

    原标题:扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!扒开伪装医用面膜,翻六倍价格宰客!当行业里的某一品项火爆了,就会有很多商家蹭热度,装逼忽悠,最近火爆朋友圈的医用面膜,被沾上了污点,到底怎么回事呢? “比普通面膜安全、效果好!痘痘、痘印、敏感肌都能用…...

    2024/5/5 8:13:33
  21. 「发现」铁皮石斛仙草之神奇功效用于医用面膜

    原标题:「发现」铁皮石斛仙草之神奇功效用于医用面膜丽彦妆铁皮石斛医用面膜|石斛多糖无菌修护补水贴19大优势: 1、铁皮石斛:自唐宋以来,一直被列为皇室贡品,铁皮石斛生于海拔1600米的悬崖峭壁之上,繁殖力差,产量极低,所以古代仅供皇室、贵族享用 2、铁皮石斛自古民间…...

    2024/5/8 20:38:49
  22. 丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者

    原标题:丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者【公司简介】 广州华彬企业隶属香港华彬集团有限公司,专注美业21年,其旗下品牌: 「圣茵美」私密荷尔蒙抗衰,产后修复 「圣仪轩」私密荷尔蒙抗衰,产后修复 「花茵莳」私密荷尔蒙抗衰,产后修复 「丽彦妆」专注医学护…...

    2024/5/4 23:54:58
  23. 广州械字号面膜生产厂家OEM/ODM4项须知!

    原标题:广州械字号面膜生产厂家OEM/ODM4项须知!广州械字号面膜生产厂家OEM/ODM流程及注意事项解读: 械字号医用面膜,其实在我国并没有严格的定义,通常我们说的医美面膜指的应该是一种「医用敷料」,也就是说,医用面膜其实算作「医疗器械」的一种,又称「医用冷敷贴」。 …...

    2024/5/9 7:32:17
  24. 械字号医用眼膜缓解用眼过度到底有无作用?

    原标题:械字号医用眼膜缓解用眼过度到底有无作用?医用眼膜/械字号眼膜/医用冷敷眼贴 凝胶层为亲水高分子材料,含70%以上的水分。体表皮肤温度传导到本产品的凝胶层,热量被凝胶内水分子吸收,通过水分的蒸发带走大量的热量,可迅速地降低体表皮肤局部温度,减轻局部皮肤的灼…...

    2024/5/9 17:11:10
  25. 配置失败还原请勿关闭计算机,电脑开机屏幕上面显示,配置失败还原更改 请勿关闭计算机 开不了机 这个问题怎么办...

    解析如下&#xff1a;1、长按电脑电源键直至关机&#xff0c;然后再按一次电源健重启电脑&#xff0c;按F8健进入安全模式2、安全模式下进入Windows系统桌面后&#xff0c;按住“winR”打开运行窗口&#xff0c;输入“services.msc”打开服务设置3、在服务界面&#xff0c;选中…...

    2022/11/19 21:17:18
  26. 错误使用 reshape要执行 RESHAPE,请勿更改元素数目。

    %读入6幅图像&#xff08;每一幅图像的大小是564*564&#xff09; f1 imread(WashingtonDC_Band1_564.tif); subplot(3,2,1),imshow(f1); f2 imread(WashingtonDC_Band2_564.tif); subplot(3,2,2),imshow(f2); f3 imread(WashingtonDC_Band3_564.tif); subplot(3,2,3),imsho…...

    2022/11/19 21:17:16
  27. 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机...

    win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”问题的解决方法在win7系统关机时如果有升级系统的或者其他需要会直接进入一个 等待界面&#xff0c;在等待界面中我们需要等待操作结束才能关机&#xff0c;虽然这比较麻烦&#xff0c;但是对系统进行配置和升级…...

    2022/11/19 21:17:15
  28. 台式电脑显示配置100%请勿关闭计算机,“准备配置windows 请勿关闭计算机”的解决方法...

    有不少用户在重装Win7系统或更新系统后会遇到“准备配置windows&#xff0c;请勿关闭计算机”的提示&#xff0c;要过很久才能进入系统&#xff0c;有的用户甚至几个小时也无法进入&#xff0c;下面就教大家这个问题的解决方法。第一种方法&#xff1a;我们首先在左下角的“开始…...

    2022/11/19 21:17:14
  29. win7 正在配置 请勿关闭计算机,怎么办Win7开机显示正在配置Windows Update请勿关机...

    置信有很多用户都跟小编一样遇到过这样的问题&#xff0c;电脑时发现开机屏幕显现“正在配置Windows Update&#xff0c;请勿关机”(如下图所示)&#xff0c;而且还需求等大约5分钟才干进入系统。这是怎样回事呢&#xff1f;一切都是正常操作的&#xff0c;为什么开时机呈现“正…...

    2022/11/19 21:17:13
  30. 准备配置windows 请勿关闭计算机 蓝屏,Win7开机总是出现提示“配置Windows请勿关机”...

    Win7系统开机启动时总是出现“配置Windows请勿关机”的提示&#xff0c;没过几秒后电脑自动重启&#xff0c;每次开机都这样无法进入系统&#xff0c;此时碰到这种现象的用户就可以使用以下5种方法解决问题。方法一&#xff1a;开机按下F8&#xff0c;在出现的Windows高级启动选…...

    2022/11/19 21:17:12
  31. 准备windows请勿关闭计算机要多久,windows10系统提示正在准备windows请勿关闭计算机怎么办...

    有不少windows10系统用户反映说碰到这样一个情况&#xff0c;就是电脑提示正在准备windows请勿关闭计算机&#xff0c;碰到这样的问题该怎么解决呢&#xff0c;现在小编就给大家分享一下windows10系统提示正在准备windows请勿关闭计算机的具体第一种方法&#xff1a;1、2、依次…...

    2022/11/19 21:17:11
  32. 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”的解决方法...

    今天和大家分享一下win7系统重装了Win7旗舰版系统后&#xff0c;每次关机的时候桌面上都会显示一个“配置Windows Update的界面&#xff0c;提示请勿关闭计算机”&#xff0c;每次停留好几分钟才能正常关机&#xff0c;导致什么情况引起的呢&#xff1f;出现配置Windows Update…...

    2022/11/19 21:17:10
  33. 电脑桌面一直是清理请关闭计算机,windows7一直卡在清理 请勿关闭计算机-win7清理请勿关机,win7配置更新35%不动...

    只能是等着&#xff0c;别无他法。说是卡着如果你看硬盘灯应该在读写。如果从 Win 10 无法正常回滚&#xff0c;只能是考虑备份数据后重装系统了。解决来方案一&#xff1a;管理员运行cmd&#xff1a;net stop WuAuServcd %windir%ren SoftwareDistribution SDoldnet start WuA…...

    2022/11/19 21:17:09
  34. 计算机配置更新不起,电脑提示“配置Windows Update请勿关闭计算机”怎么办?

    原标题&#xff1a;电脑提示“配置Windows Update请勿关闭计算机”怎么办&#xff1f;win7系统中在开机与关闭的时候总是显示“配置windows update请勿关闭计算机”相信有不少朋友都曾遇到过一次两次还能忍但经常遇到就叫人感到心烦了遇到这种问题怎么办呢&#xff1f;一般的方…...

    2022/11/19 21:17:08
  35. 计算机正在配置无法关机,关机提示 windows7 正在配置windows 请勿关闭计算机 ,然后等了一晚上也没有关掉。现在电脑无法正常关机...

    关机提示 windows7 正在配置windows 请勿关闭计算机 &#xff0c;然后等了一晚上也没有关掉。现在电脑无法正常关机以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容&#xff0c;让我们赶快一起来看一下吧&#xff01;关机提示 windows7 正在配…...

    2022/11/19 21:17:05
  36. 钉钉提示请勿通过开发者调试模式_钉钉请勿通过开发者调试模式是真的吗好不好用...

    钉钉请勿通过开发者调试模式是真的吗好不好用 更新时间:2020-04-20 22:24:19 浏览次数:729次 区域: 南阳 > 卧龙 列举网提醒您:为保障您的权益,请不要提前支付任何费用! 虚拟位置外设器!!轨迹模拟&虚拟位置外设神器 专业用于:钉钉,外勤365,红圈通,企业微信和…...

    2022/11/19 21:17:05
  37. 配置失败还原请勿关闭计算机怎么办,win7系统出现“配置windows update失败 还原更改 请勿关闭计算机”,长时间没反应,无法进入系统的解决方案...

    前几天班里有位学生电脑(windows 7系统)出问题了&#xff0c;具体表现是开机时一直停留在“配置windows update失败 还原更改 请勿关闭计算机”这个界面&#xff0c;长时间没反应&#xff0c;无法进入系统。这个问题原来帮其他同学也解决过&#xff0c;网上搜了不少资料&#x…...

    2022/11/19 21:17:04
  38. 一个电脑无法关闭计算机你应该怎么办,电脑显示“清理请勿关闭计算机”怎么办?...

    本文为你提供了3个有效解决电脑显示“清理请勿关闭计算机”问题的方法&#xff0c;并在最后教给你1种保护系统安全的好方法&#xff0c;一起来看看&#xff01;电脑出现“清理请勿关闭计算机”在Windows 7(SP1)和Windows Server 2008 R2 SP1中&#xff0c;添加了1个新功能在“磁…...

    2022/11/19 21:17:03
  39. 请勿关闭计算机还原更改要多久,电脑显示:配置windows更新失败,正在还原更改,请勿关闭计算机怎么办...

    许多用户在长期不使用电脑的时候&#xff0c;开启电脑发现电脑显示&#xff1a;配置windows更新失败&#xff0c;正在还原更改&#xff0c;请勿关闭计算机。。.这要怎么办呢&#xff1f;下面小编就带着大家一起看看吧&#xff01;如果能够正常进入系统&#xff0c;建议您暂时移…...

    2022/11/19 21:17:02
  40. 还原更改请勿关闭计算机 要多久,配置windows update失败 还原更改 请勿关闭计算机,电脑开机后一直显示以...

    配置windows update失败 还原更改 请勿关闭计算机&#xff0c;电脑开机后一直显示以以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容&#xff0c;让我们赶快一起来看一下吧&#xff01;配置windows update失败 还原更改 请勿关闭计算机&#x…...

    2022/11/19 21:17:01
  41. 电脑配置中请勿关闭计算机怎么办,准备配置windows请勿关闭计算机一直显示怎么办【图解】...

    不知道大家有没有遇到过这样的一个问题&#xff0c;就是我们的win7系统在关机的时候&#xff0c;总是喜欢显示“准备配置windows&#xff0c;请勿关机”这样的一个页面&#xff0c;没有什么大碍&#xff0c;但是如果一直等着的话就要两个小时甚至更久都关不了机&#xff0c;非常…...

    2022/11/19 21:17:00
  42. 正在准备配置请勿关闭计算机,正在准备配置windows请勿关闭计算机时间长了解决教程...

    当电脑出现正在准备配置windows请勿关闭计算机时&#xff0c;一般是您正对windows进行升级&#xff0c;但是这个要是长时间没有反应&#xff0c;我们不能再傻等下去了。可能是电脑出了别的问题了&#xff0c;来看看教程的说法。正在准备配置windows请勿关闭计算机时间长了方法一…...

    2022/11/19 21:16:59
  43. 配置失败还原请勿关闭计算机,配置Windows Update失败,还原更改请勿关闭计算机...

    我们使用电脑的过程中有时会遇到这种情况&#xff0c;当我们打开电脑之后&#xff0c;发现一直停留在一个界面&#xff1a;“配置Windows Update失败&#xff0c;还原更改请勿关闭计算机”&#xff0c;等了许久还是无法进入系统。如果我们遇到此类问题应该如何解决呢&#xff0…...

    2022/11/19 21:16:58
  44. 如何在iPhone上关闭“请勿打扰”

    Apple’s “Do Not Disturb While Driving” is a potentially lifesaving iPhone feature, but it doesn’t always turn on automatically at the appropriate time. For example, you might be a passenger in a moving car, but your iPhone may think you’re the one dri…...

    2022/11/19 21:16:57