面试题答案
一键面试- 安装依赖:
首先确保项目安装了
react
、react - dom
和typescript
,如果要使用装饰器,还需要在tsconfig.json
中开启experimentalDecorators
和emitDecoratorMetadata
:{ "compilerOptions": { "experimentalDecorators": true, "emitDecoratorMetadata": true } }
- 代码示例:
import React from'react'; // 装饰器函数 function logBeforeRender(target: any, propertyKey: string, descriptor: PropertyDescriptor) { const originalRender = descriptor.value; descriptor.value = function () { console.log('Component is about to render'); return originalRender.apply(this, arguments); }; return descriptor; } // React函数式组件 class MyComponent extends React.Component { @logBeforeRender public render() { return <div>My Component</div>; } } export default MyComponent;
- 装饰器函数参数和返回值含义:
- 参数:
target
:对于类的方法装饰器,target
是类的原型对象。在这个例子中,target
是MyComponent.prototype
。propertyKey
:被装饰的属性(方法)的名称,这里是render
。descriptor
:包含被装饰方法的属性描述符,它有value
(方法本身)、writable
、enumerable
和configurable
等属性。
- 返回值:
装饰器函数返回一个新的属性描述符(
PropertyDescriptor
),这个新的描述符会替换原来的描述符。在上述例子中,我们修改了descriptor.value
(也就是render
方法),在其执行前打印日志,然后返回修改后的descriptor
,从而实现了在组件每次渲染前打印日志的功能。
- 参数:
需要注意的是,在React函数式组件中使用类的装饰器这种方式,MyComponent
这里实际是基于类的组件写法。如果是纯粹的函数式组件,可以使用自定义的高阶组件(HOC)来实现类似功能,如下:
import React from'react';
// 高阶组件实现日志记录
function withLog(Component: React.FC) {
return (props: React.PropsWithChildren) => {
console.log('Component is about to render');
return <Component {...props} />;
};
}
// 函数式组件
const MyFunctionalComponent: React.FC = () => {
return <div>My Functional Component</div>;
};
const LoggedComponent = withLog(MyFunctionalComponent);
export default LoggedComponent;
在这个高阶组件版本中,withLog
函数接受一个组件Component
作为参数,返回一个新的组件,新组件在渲染传入的Component
之前打印日志。