-
Notifications
You must be signed in to change notification settings - Fork 16
/
index.ts
79 lines (65 loc) · 2.25 KB
/
index.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
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
import { IChangesObject } from 'angular'
import assign = require('lodash/assign')
import mapValues = require('lodash/mapValues')
import some = require('lodash/some')
type OnChanges<T> = {
[K in keyof T]: IChangesObject<T[K]>
}
abstract class NgComponent<
Props extends { [k: string]: any } = {},
State extends { [k: string]: any } = {}
> {
private __isFirstRender = true
protected state: State = {} as State
public props: Partial<Props> = {} as Partial<Props>
/*
eg. {
as: {currentValue: [1, 2, 3], previousValue: [1, 2]},
bs: {currentValue: 42, previousValue: undefined}
}
*/
// nb: this method is explicity exposed for unit testing
public $onChanges(changes: OnChanges<Partial<Props>>) {
const oldProps = this.props
// TODO: fix Lodash typings upstream
const newProps = mapValues(changes, 'currentValue') as Partial<Props>
// TODO: implement nextState (which also means implement this.setState)
const nextProps = assign({}, this.props, newProps)
if (this.__isFirstRender) {
assign(this, { props: nextProps })
this.componentWillMount()
this.render()
this.__isFirstRender = false
} else {
if (!this.didPropsChange(newProps, oldProps)) return
this.componentWillReceiveProps(nextProps)
const shouldUpdate = this.shouldComponentUpdate(nextProps, this.state)
assign(this, { props: nextProps })
if (!shouldUpdate) return
this.componentWillUpdate(this.props, this.state)
this.render()
this.componentDidUpdate(this.props, this.state)
}
}
$postLink() {
this.componentDidMount()
}
$onDestroy() {
this.componentWillUnmount()
}
protected didPropsChange(newProps: Partial<Props>, oldProps: Partial<Props>): boolean {
return some(newProps, (v, k) => v !== oldProps[k])
}
/*
lifecycle hooks
*/
componentWillMount(): void {}
componentDidMount(): void {}
componentWillReceiveProps(_props: Partial<Props>): void { }
shouldComponentUpdate(_nextProps: Partial<Props>, _nextState: State): boolean { return true }
componentWillUpdate(_props: Partial<Props>, _state: State): void {}
componentDidUpdate(_props: Partial<Props>, _state: State): void {}
componentWillUnmount() {}
render(): void {}
}
export default NgComponent