Angular 组件您可以将原始版本中的 React 组件替换为它们的 Angular 等效组件 — 并迅速得到一个 Angular 图书搜索应用程序。Angular 版本中的 reducer、操作、存储和状态历史都与 React 版本相同。
与 React 一样,借助 Angular,您可以实现彼此嵌套的组件。清单 6 给出了 App 组件,它包含应用程序中的其他所有组件。
清单 6. App 组件 (app/components/app.component.ts)1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
| import { Component } from '@angular/core';
import Books from './books.component';
import Controls from './controls.component';
import StateViewer from './stateviewer.component';
import store from '../../store';
import { fetchBooks, setTopic } from '../../actions';
@Component({
selector: 'app',
template: `
<div style='text-align: center; font-size: 1.5em'>
{{app.title}}
</div>
<hr/>
<controls></controls>
<books></books>
<state-viewer></state-viewer>`
})
export default class {
ngOnInit() {
store.dispatch(setTopic('Border collies'));
store.dispatch(fetchBooks());
}
app = {
title: 'Book Search (Angular version)',
};
}
|
App 组件模板包含 3 个组件:controls、books 和 state-viewer。该组件的 TypeScript 在初始化 App 组件时向 Redux 存储分派操作。
controls 组件如清单 7 所示。
清单 7. controls 组件 (app/components/controls.component.ts)1
2
3
4
5
6
7
8
9
10
11
12
13
| import { Component } from '@angular/core';
@Component({
selector: 'controls',
template: `
<topic-selector></topic-selector>
<display-mode-container></display-mode-container>
<history></history>
`
})
export default class Controls {
}
|
controls 组件不执行任何操作,仅包含其他组件,所以它的关联类的实现是空的(但仍然必不可少)。
topic-selector 组件如清单 8 所示。
清单 8. TopicSelector 组件 (app/components/topicselector.component.ts)1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
| import { Component } from '@angular/core';
import { fetchBooks, setTopic } from '../../actions';
import store from '../../store';
@Component({
selector: 'topic-selector',
template: `
<label for='topic'>Topic</label>
<input #topicInput
[(ngModel)]='topic'
(input)='setTopic(topicInput.value)'
(keyup.enter)='fetchTopic(topicInput.value)'
autofocus/>
`
})
export default class TopicSelector {
private topic: string;
private unsubscribe: any;
constructor() {
store.subscribe(() => {
this.topic = store.getState().topic;
});
}
setTopic(newTopic) {
store.dispatch(setTopic(newTopic));
}
fetchTopic(newTopic) {
store.dispatch(fetchBooks());
}
ngOnDestroy() {
this.unsubscribe();
}
}
|
主题选择器包含一个标签和一个输入用于指定新主题。输入的 keyup.enter 事件对应于该组件的 fetchTopic() 方法,input 事件对应于该组件的 setTopic() 方法。因此,每次击键都会更新该主题,而且在用户按 Enter 键时会发起一次新的抓取。 |