关于高阶组件的一点思考:
很喜欢用高阶组件这种形式 高阶组件和高阶函数:本质上都是对输入的函数或者组件在不改变原输入函数(或组件)的前提下,对一个功能(或ui)的增强
UI:这是为了增加一个label,比较简单
export const withLabel = (Component: React.FunctionComponent<any>) => (props: Record<string, any>) => {
const { label, ...otherProps } = props;
return (
<div style={{ display: 'flex' }}>
<LabelComponent label={label} />
<Component {...otherProps} />
</div>
);
};
export const withHiddenStatus = (Component: React.FunctionComponent<any>) => (props: Record<string, any>) => {
const { hidden, ...otherProps } = props;
if (hidden === true) {
return <div></div>;
}
return <Component {...otherProps} />;
};
这个高阶组件是为了给原有组件添加协议,起作用是给传入组件的props注入一个ui和一个检测函数,在尽可能少的改变原有组件的前提下增强起隐私协议功能,有的页面是公用的,但是一个页面有好几个地址,只有规定地址的页面才使用该协议
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
// import { makeAutoObservable } from 'mobx'
import { observer } from 'mobx-react-lite';
import st from './index.scss';
import cn from 'classnames';
import Wearning from './Wearning';
import { CONTRACT_TIPS_SHORT, HREF } from './const';
import CheckedBox from './CheckedBox';
function PrivacyAgreement({
check,
setCheck,
openWearning,
wearningText,
text1 = '我已阅读并同意',
text2 = CONTRACT_TIPS_SHORT,
}) {
const turnCheck = ()=>setCheck(!check);
return (
<>
<div
className={cn({
[st.box]: true,
'privacyAgreement-margin': true
})}
>
{!check ? (
<div
className={cn({
[st.checkBox_common]: true,
[st.checkBox]: true
})}
onClick={turnCheck}
></div>
) : (
<div
className={cn({
[st.checkBox_common]: true,
[st.on]: true
})}
onClick={turnCheck}
>
<CheckedBox />
</div>
)}
<span className={st.text1}>{text1}</span>
<a
href={HREF}
target="_blank"
rel="noreferrer"
className={st.text2}
>
{text2}
</a>
<div className={st.wearning}>
<Wearning
openWearning={openWearning}
wearningText={wearningText}
/>
</div>
</div>
</>
)
}
export const withPrivacyAgreement = (Components, config={}) => {
const wearningText = "请勾选同意"+`${config.text2||CONTRACT_TIPS_SHORT}`
const time = config?.time || 3000;
const defaultPagePath = [
'/xxx/1.html',
'/xxx/2.html',
'/xxx/3.html',
'/xxx/4.html',
'/xxx/5.html',
'/xxx/6.html',
'/xxx/7.html'
];
const display_name = config?.displayName || 'privacyAgreement';
const getPreFixName = (config,key)=>config?.displayName?config.displayName+`_${key}`:key;
const before_submit = getPreFixName(config,'beforeSubmit');
const getPA = () => {
const pathName = window.location.pathname;
return !!(config?.hasShow || defaultPagePath.includes(pathName));
};
const before_setCheck = getPreFixName(config,'setCheck');
const display_check = getPreFixName(config,'check');
return (props) => {
const hasPA = useRef(getPA());
const [check, setCheck] = useState(false);
const [openWearning, setOpenWearning] = useState(false);
const beforeSubmit = useCallback(() => {
if (!hasPA.current) return true;
if (check) return true;
setOpenWearning(true);
setTimeout(() => {
setOpenWearning(false);
}, time);
return false;
}, [check]);
if (!hasPA.current)
return (
<Components
{...props}
{...{
[before_setCheck]: () => {},
[display_name]: null,
[before_submit]: () => true,
}}
/>
);
const privacyAgreement = useMemo(
() => (
<PrivacyAgreement
check={check}
setCheck={setCheck}
{...config}
openWearning={openWearning}
wearningText={wearningText}
time={time}
/>
),
[check, openWearning, wearningText, time],
);
const _props = {
...props,
[display_check]:check,
[before_setCheck]:setCheck,
[display_name]:privacyAgreement,
[before_submit]:beforeSubmit,
};
return <Components {..._props} />;
};
};
总结:网上总说现在是函数组件了 不再使用class组件,就可以不用高阶组件,但是我认为 不管是对类还是函数组件来讲, 高阶组件其本质是一种思想,是装饰者模式的一种实践,和高阶函数是一样的,不论是不是函数组件还是累组件都可以使用