面试题答案
一键面试1. componentDidMount行为差异
- 服务端渲染(SSR)场景:
- 在SSR过程中,
componentDidMount
不会在服务端执行。因为SSR主要是在服务器端生成初始的HTML,这个阶段并没有真实的DOM环境,而componentDidMount
依赖于真实DOM的存在。
- 在SSR过程中,
- 客户端水合(Hydration)场景:
- 当客户端接收到服务端传来的HTML,并进行水合操作后,
componentDidMount
会在组件挂载到真实DOM后执行。此时,组件已经有了真实的DOM环境,可以进行DOM操作、数据获取等操作。
- 当客户端接收到服务端传来的HTML,并进行水合操作后,
2. 确保逻辑正确执行且不冲突的方法
- 数据获取:
- 服务端预取数据:在SSR阶段,可以通过在
getServerSideProps
(对于Next.js应用)或类似的服务器端数据获取方法,在服务器端获取数据,并将其作为props传递给组件。这样,在客户端水合时,组件可以直接使用已经获取的数据,避免重复获取。 - 条件判断:在
componentDidMount
中,可以通过检查数据是否已经存在于props中来决定是否再次获取数据。
- 服务端预取数据:在SSR阶段,可以通过在
- DOM操作:
- 检查DOM存在:在进行DOM操作前,确保DOM元素已经存在。可以使用
document.getElementById
等方法先检查元素是否存在,避免在SSR阶段(无真实DOM)执行DOM操作导致错误。
- 检查DOM存在:在进行DOM操作前,确保DOM元素已经存在。可以使用
3. 代码示例(以Next.js为例)
import React, { Component } from'react';
class MyComponent extends Component {
constructor(props) {
super(props);
this.state = {
data: props.initialData || null
};
}
componentDidMount() {
if (!this.state.data) {
// 如果数据在服务端未预取,则在客户端获取
fetch('/api/data')
.then(response => response.json())
.then(data => this.setState({ data }));
}
// DOM操作示例
const element = document.getElementById('my-element');
if (element) {
element.style.color = 'blue';
}
}
render() {
return (
<div>
<div id="my-element">
{this.state.data? `Data: ${this.state.data}` : 'Loading...'}
</div>
</div>
);
}
}
export async function getServerSideProps() {
const response = await fetch('/api/data');
const data = await response.json();
return {
props: {
initialData: data
}
};
}
export default MyComponent;
在上述代码中:
getServerSideProps
在服务端获取数据,并通过props传递给组件。- 在
componentDidMount
中,先检查this.state.data
是否存在,如果不存在则在客户端再次获取数据。同时,在进行DOM操作前,先检查DOM元素是否存在,以确保在SSR和客户端水合场景下都能正确执行逻辑且不冲突。