1
- // 高阶组件 用于提取重复逻辑
2
-
1
+ //高阶组件 用于提取重复逻辑
3
2
import React from 'react'
4
3
5
- let _this : any = null
6
- let _isPop = false //是否触发过popState
7
- let _isMount = false //组件是否挂载完成
4
+ let _this = null
5
+
8
6
const popStateCallback = ( ) => {
9
- // 使用 popStateCallback 保存函数防止 addEventListener 重复注册
7
+ // 使用popStateFn保存函数防止addEventListener重复注册
10
8
if ( _this && _this . getInitialProps ) {
11
9
console . log ( 'popStateFn' )
12
- _isPop = true
13
- if ( _isMount ) {
14
- //只有当前组件挂载后才能执行数据预取,否则会报错
15
- _this . getInitialProps ( )
16
- }
10
+ _this . getInitialProps ( )
17
11
}
18
12
}
19
13
20
- export default ( SourceComponent : any ) => {
21
- return class HoComponent extends React . Component < any , any > {
22
- constructor ( props : any ) {
14
+ export default SourceComponent => {
15
+ return class HoComponent extends React . Component {
16
+ constructor ( props , context ) {
23
17
super ( props )
24
-
18
+ console . log ( 'props' , props )
25
19
this . state = {
26
20
initialData : { } ,
27
- canClientFetch : false // 浏览器端是否需要请求数据
21
+ canClientFetch : false //浏览器端是否需要请求数据
28
22
}
29
23
}
30
- // 用于服务端调用
31
- static async getInitialProps ( ctx : any ) {
24
+
25
+ //转接子组件的预取方法,服务端会调用这个方法来做数据预取
26
+ static async getInitialProps ( ctx ) {
32
27
return SourceComponent . getInitialProps
33
28
? await SourceComponent . getInitialProps ( ctx )
34
29
: { }
35
30
}
36
-
37
- //用于封装处理
31
+ // ! csr/ssr切换路由时才调用组件的getInitialProps方法
32
+ //用于封装处理数据的更新逻辑
38
33
async getInitialProps ( ) {
39
34
// ssr首次进入页面以及csr/ssr切换路由时才调用组件的getInitialProps方法
40
- const { match, location } = this . props
35
+ const props = this . props
36
+ const store = window . __STORE__ //从全局得到 store
37
+
38
+ // 兼容不使用 redux 的页面
39
+ // 通过props.getInitialData判断
40
+ // ! 那就说明约定getInitialData
41
41
const res = SourceComponent . getInitialProps
42
- ? await SourceComponent . getInitialProps ( { match , location } )
42
+ ? await SourceComponent . getInitialProps ( { store } )
43
43
: { }
44
- this . setState ( {
45
- initialData : res ,
46
- canClientFetch : true
47
- } )
48
-
49
- console . log ( 'getInitialProps' )
50
- let { tdk } = res . page
44
+ //处理页面 title 显示
45
+ let { tdk } = res . page || { }
51
46
if ( tdk ) {
52
47
document . title = tdk . title
53
48
}
54
49
}
55
50
56
51
async componentDidMount ( ) {
57
- //注册事件,用于在页面回退和前进的时候触发
58
- _isMount = true //组件挂载完成
59
- // @ts -ignore
60
- if ( window . __IS__SSR__ ) {
61
- //只有当启用 ssr 时
62
- _this = this // 修正_this指向,保证_this指向当前渲染的页面组件
63
- //注册事件
64
- window . addEventListener ( 'popstate' , popStateCallback )
65
-
66
- if ( _isPop ) {
67
- //如果前进或者后退 则需要异步获取数据
68
- this . getInitialProps ( )
69
- }
70
- }
52
+ _this = this // 修正_this指向,保证_this指向当前渲染的页面组件
53
+ //注册事件,用于在页面回退的时候触发
54
+ window . addEventListener ( 'popstate' , popStateCallback )
71
55
72
56
const canClientFetch = this . props . history && this . props . history . action === 'PUSH' //路由跳转的时候可以异步请求数据
73
- console . log ( 'canClientFetch' , canClientFetch )
74
- // @ts -ignore
75
- if ( canClientFetch || ! window . __IS__SSR__ ) {
57
+ if ( canClientFetch ) {
58
+ //如果是 history PUSH 操作 则更新数据
76
59
await this . getInitialProps ( )
77
60
}
78
61
}
79
62
80
- componentWillUnmount ( ) {
81
- console . log ( 'unmount' )
82
- _isPop = false //重置为未触发
83
- _isMount = false //重置为未挂载
84
- }
85
-
86
63
render ( ) {
87
- // 只有在首次进入页面需要将window.__INITIAL_DATA__作为props,路由切换时不需要
88
-
89
64
const props = {
90
65
initialData : { } ,
91
66
...this . props
92
67
}
93
- // @ts -ignore
94
68
95
69
if ( __SERVER__ ) {
96
70
//服务端渲染
@@ -101,9 +75,7 @@ export default (SourceComponent: any) => {
101
75
//需要异步请求数据
102
76
props . initialData = this . state . initialData || { }
103
77
} else {
104
- // @ts -ignore
105
78
props . initialData = window . __INITIAL_DATA__
106
- // @ts -ignore
107
79
window . __INITIAL_DATA__ = null //使用过后清除数据,否则其他页面会使用
108
80
}
109
81
}
0 commit comments