重学react——高阶组件

一、高阶组件基础

一句话:就是一个函数,传入一个组件,返回一个新组件;作用就是对传入的组件进行了增强

const lessons = [
    {stage: 'react', title: '组件化1'},
    {stage: 'react', title: '组件化2'},
    {stage: 'react', title: '组件化3'}
];

// 函数组件
function Lesson(props: any) {
    return 
{props.stage} - {props.title}
; } const withContent = (Comp: any) => (props: any) => { const content = lessons[props.idx]; return ; }; // 高阶组件 const LessonContent = withContent(Lesson); // 高阶组件的运用

另外我们都知道ES6中的一种语法叫做装饰器,用在组件上和高阶组件也是一样的,只不过装饰器只能用在类组件中

const withContent2 = (Comp: any) => {
    return class extends React.Component {
        render() {
            const content = lessons[this.props.idx];
            return ;
        }
    };
};

@withContent2
class Lesson2Content extends React.Component {
    render() {
        return 
{this.props.stage} - {this.props.title}
; } } // 运用

二、利用高阶组件简单实现antd中的表单验证

1、先看一下antd用法

import { Form, Icon, Input, Button } from 'antd/es';

class HorizontalLoginForm extends React.Component {

    handleSubmit = e => {
        e.preventDefault();
        this.props.form.validateFields((err, values) => {
            if (!err) {
                console.log('Received values of form: ', values);
            }
        });
    };

    render() {
        const { getFieldDecorator} = this.props.form;
        return (
            
{getFieldDecorator('username', { rules: [{ required: true, message: 'Please input your username!' }], })( } placeholder="Username" />, )}
); } } const WrappedHorizontalLoginForm = Form.create({ name: 'horizontal_login' })(HorizontalLoginForm);

2、我们实现一下Form.create

用kFormCreate代替Form.create
(1)

const kFormCreate = (Form: any) => {

    return (props: any) => {
        // state存储value键值对 name: value
        const [state, setState] = useState({});
        // 存储存在的错误信息 name: errMsg
        const [errMsg, setErrMsg] = useState({});
        // 存储当前验证的键值 name
        const validateKey = useRef('');
        // 存储各个键值的验证选项 name: {rules:[{required:..., ...}]}
        const options = useRef({});
        
        // 表单change事件,改变state并触发单项校验
        const handleChange = (e: any) => {
            const {name, value} = e.target;
            // 表单change时,存储当前需要验证的键值
            validateKey.current = name;
            setState((state: any) => ({
                ...state,
                [name]: value
            }));
        };
        
        // 单项校验,依赖于options, state,但是主要依赖state变化,也就是表单value的变化,而options只有getFiledDec方法初始化表单时改变options(此时validateKey.current为空,因此走不到单项校验里)
        const validateFiled = useCallback((field: string) => {
            const {rules} = options.current[field];
            const value = state[field];
            const ret = !rules.some((rule: any) => {
                if (rule.required && !value) {
                    setErrMsg((err: any) => ({
                        ...err,
                        [field]: rule.message
                    }));

                    return true;
                }
                return false;
            });

            if (ret) {
                setErrMsg((err: any) => ({
                    ...err,
                    [field]: ''
                }));
            }

            return ret;
        }, [options, state]);


        useEffect(() => {
            // 监控 validateFiled 变化,一但变化就进行单项校验
            if (validateKey.current) {
                validateFiled(validateKey.current);
            }

        }, [validateFiled]);

        // 传入校验规则返回一个高阶组件
        const getFiledDec = (field: string, option: object) => {
            // 添加校验选项
            options.current[field] = option;
            
            // 高阶组件
            return (InputComp: any) => {
                return 
{ React.cloneElement(InputComp, { name: field, value: state[field] || '', onChange: handleChange }) } { !!errMsg[field] &&
{errMsg[field]}
}
; }; }; // 提交校验(整体校验) const validateFileds = (cb: (res:any) => {}) => { const ret = Object.keys(options.current).every((key: string) => { return validateFiled(key); }); if (ret) { cb(state); } }; return
; }; };

3、使用

const KForm = (props: any) => {
    const {getFiledDec, validateFileds} = props;
    const onSubmit = () => {
        validateFileds((res: any) => {
            console.log(res);
        });
    };

    return 
{ getFiledDec('username', { rules: [{required: true, message: 'Please input your username!'}] })() } { getFiledDec('password', { rules: [{required: true, message: 'Please input password!'}] })() }
; }; const MyForm = kFormCreate(KForm); export default () => { return
; }

你可能感兴趣的:(javascript,前端,es6,hook,react.js)