【发布时间】:2018-10-02 14:17:30
【问题描述】:
我目前正在通过制作一个小项目来学习如何正确使用 Angular(版本 5+)。我已经设置了一些基本路由,通过选择导航选项卡来加载 ContactList 组件。另一个选项卡允许使用表单添加联系人,然后将表单数据发送到联系人数据服务,其中联系人在数组中进行管理。 ContactList 组件如下:
import { Component, OnInit, Input, Output,
OnChanges, DoCheck, SimpleChanges} from '@angular/core';
import { ContactDataService } from '../ContactData.service';
// import { FilterPipe } from '../../../src/pipes';
import { Contact } from '../contact.model';
@Component({
selector: 'app-contact-list-component',
templateUrl: './contact-list-component.component.html',
styleUrls: ['./contact-list-component.component.css']
})
export class ContactListComponent implements OnInit, OnChanges, DoCheck {
contactList: Contact[] = [];
searchQuery: string; // alternate subscribed data from contactDataService
contactServObj: ContactDataService;
constructor(contactServObj: ContactDataService) {
this.contactServObj = contactServObj;
}
ngOnChanges(changes: SimpleChanges) {
console.log('ngOnChanges called!');
console.log(changes);
for (const key of Object.keys(changes)) {
console.log(`${key} changed.Current: ${changes[key].currentValue}.Previous: ${changes[key].previousValue}`);
}
}
ngOnInit() {
this.contactList = this.contactServObj.getContacts();
// console.log('ngOnInit called!');
this.contactServObj.queryString.subscribe((query: string) => {
this.searchQuery = query;
});
}
ngDoCheck() {
console.log('ngDoCheck called!');
}
}
联系人数据服务(其中管理联系人数组)如下:
import { EventEmitter } from '@angular/core';
import { Contact } from './contact.model';
export class ContactDataService {
private contactList: Contact[] = [];
getContacts() {
return this.contactList;
}
sortContactHandler = (value) => {
console.log(value);
const field = value === 'default' ? null : value;
if (this.contactList.length > 1 && field !== null) {
this.contactList.sort(this.compareValues(field, 'asc'));
console.log(this.contactList);
}
}
compareValues = (key, order= 'asc') => {
return function(a, b) {
if (!a.hasOwnProperty(key) ||
!b.hasOwnProperty(key)) {
return 0;
}
const varA = (typeof a[key] === 'string') ?
a[key].toUpperCase() : a[key];
const varB = (typeof b[key] === 'string') ?
b[key].toUpperCase() : b[key];
let comparison = 0;
if (varA > varB) {
comparison = 1;
} else if (varA < varB) {
comparison = -1;
}
return (
(order === 'desc') ?
(comparison * -1) : comparison
);
};
}
addContactHandler(sentContact: Contact) {
let field = '';
const findExistingContact = this.contactList.findIndex((el, i) => {
// return (name === el.name) || (phone === el.phone) || (email === el.email);
if (sentContact.name === el.name) {
field = 'name';
return true;
} else if (sentContact.phone === el.phone) {
field = 'phone';
return true;
} else if (sentContact.email === el.email) {
field = 'email';
return true;
}
return false;
});
console.log(findExistingContact);
if (findExistingContact === -1) {
const newContact: Contact = sentContact;
this.contactList.push(newContact);
} else {
alert(`Contact with field ${field} already exists!`);
}
}
}
Contact Data Service 在根级别注入 - 在 app.module.ts 中,如下所示:
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { Routes, RouterModule } from '@angular/router';
import { AppComponent } from './app.component';
import { ContactComponent } from './contact-component/contact-component.component';
import { ContactListComponent } from './contact-list-component/contact-list-component.component';
import { AddContactComponent } from './add-contact-component/add-contact-component.component';
import { SearchContactComponent } from './search-contact-component/search-contact-component.component';
import { BackdropComponent } from './backdrop/backdrop.component';
import { ModalComponent } from './modal/modal.component';
import { EditContactComponent } from './edit-contact/edit-contact.component';
import { ContactDataService } from './ContactData.service';
import { ModalShowService } from './modal-show.service';
import { CockpitComponentComponent } from './cockpit-component/cockpit-component.component';
import { FilterContactPipe } from './filter-contact.pipe';
import { SortComponent } from './sort/sort.component';
import { ContactDetailComponent } from './contact-detail/contact-detail.component';
const appRoutes: Routes = [
{ path: '' , component: AddContactComponent },
{ path: 'contactList', component: ContactListComponent },
{ path: 'contactList/:name', component: ContactDetailComponent }
];
@NgModule({
declarations: [
AppComponent,
ContactComponent,
ContactListComponent,
AddContactComponent,
SearchContactComponent,
BackdropComponent,
ModalComponent,
EditContactComponent,
CockpitComponentComponent,
FilterContactPipe,
SortComponent,
ContactDetailComponent
],
imports: [
BrowserModule,
FormsModule,
RouterModule.forRoot(appRoutes)
],
providers: [ContactDataService, ModalShowService],
bootstrap: [AppComponent]
})
export class AppModule { }
最后,我有一个排序组件,它只是一个简单的下拉选择框,其中包含用于对联系人进行排序的 3 个字段。它所做的只是将这个字段发送到联系人数据服务中的 sortContactHandler 函数,我在 console.log(this.contactList) 语句中看到了这个结果。但是这种变化并没有反映在呈现数组的 ContactList 组件中。
问题:将这个排序后的contactList 数组放入我的ContactList 组件的最佳方法是什么(它只在ngOnInit() 函数中检索这个数组)?
我认为这可以使用生命周期钩子来完成,所以我试图理解它们,但也许我做错了什么。 ngOnChanges() 永远不会被调用(我从未在该函数中看到过 console.log()),而且我不确定如何使用 ngDoCheck()。另外,从我对上述生命周期方法的阅读中可以看出,它们会对组件输入属性的变化做出反应,所以我不确定它们是否可以在我的情况下使用。
这是StackBlitz的问题
【问题讨论】:
-
你知道 Angular 中的依赖注入吗? angular.io/guide/dependency-injection
-
是的,我知道它的要点。我将编辑我的问题以显示服务的注入位置。但这不是问题所在;问题是,我们如何将服务中最新更新的数组检索到组件中?
-
当您在根模块的 providers 数组中设置 DataService 时,它会成为整个应用程序的 Singleton。这意味着,当有人在其中更改
contactList时,通过依赖注入指向该对象的任何其他组件的属性都将具有它的最新值。所以这里一切都很好。您可以在 StackBlitz.com 中展示您的 gitHub 或重现问题吗? -
用 StackBlitz 中的代码更新问题
标签: javascript arrays angular