Как React оборачивает простой компонент

React.js

предисловие

В мгновение ока прошло больше года с тех пор, как я познакомился с React. С самого начала резюме, изучение грамматики, а теперь написание функциональных компонентов и упаковки. Поделитесь некоторыми мыслями.

1. Component

Начало компонентов в реакции. Сначала проанализируйте это

    //生命周期的接口
    interface Component<P = {}, S = {}, SS = any> extends ComponentLifecycle<P, S, SS> { }
    class Component<P, S> {
    
        //构造函数
        constructor(props: Readonly<P>);
        constructor(props: P, context?: any);
        //我们更新组件的setState
        setState<K extends keyof S>(
            state: ((prevState: Readonly<S>, props: Readonly<P>) => (Pick<S, K> | S | null)) | (Pick<S, K> | S | null),
            callback?: () => void
        ): void;

        forceUpdate(callBack?: () => void): void;
        //组件的逻辑
        render(): ReactNode;
        readonly props: Readonly<{ children?: ReactNode }> & Readonly<P>;
        //state对象
        state: Readonly<S>;
        context: any;
        //组件引用
        refs: {
            [key: string]: ReactInstance
        };
    }

Обычно пишут компоненты, всего 4 часто используемых

render state setState refs

Некоторые скажут, иconstructorШерстяная ткань.

На самом деле, я почти не использую его.

constructor

В первые дни реакции рутина должна быть такой:

Определение состояния и определение функции находятся в конструкторе. Я все еще вижу много людей, которые пишут это На самом деле, в этом нет ничего плохого.

Но я думаю, что React, JSX, ES6 - хорошие места. Все делают JS больше похожи на скомпилированный язык, а не языком сценариев. Говорить прямо. Очень похоже на язык, как Java

Как писал java человек несколько лет, я лично думаю, что это выглядит намного удобнее Ха-ха.

Этот логотип тоже достался по наследству, пристыкован.

Основная тема:

На самом деле, независимо от того, на каком языке, Разработка и дизайн должны следовать шести принципам дизайна:

Принцип единой ответственности (SRP):一个组件只做一件事

Принцип замены Лисков (LSP):继承

Принцип инверсии зависимостей (DIP):多态

Принцип разделения интерфейсов (ISP):不要滥用接口(别继承没用的)

Закон Деметры (LOD):耦合

Открытый закрытый принцип (OCP):扩展性强(逻辑写好了别瞎JB改.要让人能扩展)

Впринципе не сложно, но чтобы действительно сделать хорошо, еще нужны технологии (ерунда).


Самый практичный:

单一职责原则 里氏替换原则 开闭原则

Из кода, который я видел в группе обмена, и кода, который я видел, включая самого себя. Эти три являются наиболее часто используемыми, но их легче всего упустить из виду.

Перестаньте нести чушь.

Пример: Напишите временное переключение контента

Во-первых, подумайте о требовании (единичное обвинение), постарайтесь не усложнять, не думайте слишком много.

1. Анализ требований, определение параметров:

параметр:

1. Интервальное время

2. Текущее отображаемое содержимое (одно или несколько)

3. начать, пауза

Перезвоните:

обратный вызов для каждого коммутатора

определение:

/**
 * 定时切换
 */
class Test extends Component {
    state = {
 
    };

    render() {
        const { time, open, children } = this.props;
        return (
            <div>

            </div>
        );
    }
}

Test.propTypes = {
    // 间隔时间
    time: PropTypes.number,
    // 是否启动
    open: PropTypes.bool,
};

export default Test;

2. Показать содержимое

Некоторые спросят, почему не определены параметры отображения контента.

Это включает в себя реакцию.childrenЭтот параметр есть.

childrenв отладить посмотри

Так что для отображения содержимого нет необходимости специально писать параметр. инициализация


    componentDidMount() {
        this.notifyContent();
    }

    componentDidUpdate(prevProps, prevState, snapshot) {
        if (this.props.children !== prevProps.children) {
            this.notifyContent();
        }
    }

    notifyContent = () => {
        const { children } = this.props;
        const content = Array.isArray(children) ? children : [children];
        this.setState({
            content,
        });
    };

3. Напишите цикл времени

Здесь он написан рекурсивно с посещением.

    componentDidMount() {

        this.loop();
    }

    componentDidUpdate(prevProps, prevState, snapshot) {
        if (this.props.open !== prevProps.open) {
            this.loop();
        }
    }
    loop = () => {
        const { time = 1000, open = false } = this.props;
        //如果没开就关闭
        if (!open) {
            return;
        }
        setTimeout(() => {
            const { content, index } = this.state;
            const newIndex = index + 1;
            this.setState({
                index: newIndex >= content.length ? 0 : newIndex
            });
            this.loop();
        }, time);
    };

4. Обратный звонок при переключении

Преобразуйте цикл и добавьте метод изменения в середине

    loop = () => {
        const { time = 1000, open = false } = this.props;
        if (!open) {
            return;
        }
        setTimeout(() => {
            const { content, index } = this.state;
            this.change(index, content[index]);
            
            const newIndex = index + 1;
            this.setState({
                index: newIndex >= content.length ? 0 : newIndex
            });
            this.loop();
        }, time);
    };

    change = (index, content) => {
        const { onChange, change } = this.props;
        if (onChange) { //antd的form表单,默认会设置.
            onChange(index, content);
        }
        if (change) {//所以一般写2个.
            change(index, content);
        }
    };

5. Что делать, если я хочу добавить расширения?

    getItem = (index) => {
        const { wrapper } = this.props;
        const item = this.state.content[index];
        if (wrapper) {
            return wrapper(item, index);
        }
        return item;
    };

наконец

import React, { Component } from 'react';
import PropTypes from 'prop-types';

/**
 * 定时切换
 */
class Test extends Component {
    state = {
        index: 0,
        content: [],
    };

    componentDidMount() {
        this.notifyContent();
        this.loop();
    }

    componentDidUpdate(prevProps, prevState, snapshot) {
        if (this.props.open !== prevProps.open) {
            this.loop();
        }
        if (this.props.children !== prevProps.children) {
            this.notifyContent();
        }
    }
    //更新,保存主内容引用
    notifyContent = () => {
        const { children } = this.props;
        const content = Array.isArray(children) ? children : [children];
        this.setState({
            content,
        });
    };
    // 定时循环
    loop = () => {
        const { time = 1000, open = false } = this.props;
        if (!open) {
            return;
        }
        setTimeout(() => {
            const { content, index } = this.state;
            this.change(index, content[index]);
            
            const newIndex = index + 1;
            this.setState({
                index: newIndex >= content.length ? 0 : newIndex
            });
            this.loop();
        }, time);
    };
    // 改变回调
    change = (index, content) => {
        const { onChange, change } = this.props;
        if (onChange) { //antd的form表单,默认会设置.
            onChange(index, content);
        }
        if (change) {//所以一般写2个.
            change(index, content);
        }
    };
    // 获取展示内容
    getItem = (index) => {
        const { wrapper } = this.props;
        const item = this.state.content[index];
        if (wrapper) {
            return wrapper(item, index);
        }
        return item;
    };

    render() {
        const { index } = this.state;
        return (
            <div>
                {this.getItem(index)}
            </div>
        );
    }
}

Test.propTypes = {
    time: PropTypes.number,
    open: PropTypes.bool,
    wrapper: PropTypes.func,
    change: PropTypes.func,
};

export default Test;

использовать

    <Test
      open={true}
      time={5000}
      change={(i, item) => {
         console.log(i, item);
      }}>
      <p>1</p>
      <p>2</p>
      <p>3</p>
    </Test>

Эпилог

Не так просто

propTypes - это хорошо, нужно использовать (если вы хотите хорошо поддерживать свои кодовые слова)

Эффект не выложится.Гифку сделать немного хлопотно.Если интересно,можете скопировать и запустить напрямую.

Приветствую всех, чтобы поставить лайк и оставить сообщение