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