Суть React! Полное резюме (быстро)

React.js
Человек не рожден для того, чтобы быть побежденным, его можно сколько угодно уничтожать, но победить его нельзя. 

Я изучаю и использую React больше года. Недавно я хочу разобраться с базовыми знаниями React, закрепить фундамент и смело продвигаться вперед~ Информация о reacr-router, redux, redux-saga будет медленно выходить в будущем, надеюсь, вы продолжите обращать на это внимание~~ Если вы поставите лайк, чтобы поощрить это, будет еще большеотличныйсейчас~

напоминать: После прочтения поторопитесь и куйте железо, пока горячо, редукс, реакт-редукс, редукс-сага

Статья, резюмирующая Redux, React-Redux, Redux-Saga.

Краткий обзор основ реагирования

1. Что такое JSX?

Пример синтаксиса JSX показан ниже.

const element = <h1>Hello, world!</h1>;

Эта форма синтаксиса не является ни HTML, ни строкой, но называется JSX, который представляет собой синтаксис, используемый для описания пользовательского интерфейса и стилей в React. JSX в конечном итоге будет скомпилирован в допустимые вызовы операторов JS (когда компилятор сталкивается с{При использовании синтаксиса JS для синтаксического анализа столкнитесь<Используйте правила HTML для синтаксического анализа)

2. Встроенные выражения

В JSX можно использовать фигурные скобки{}Вставьте любое допустимое выражение JavaScript, например:2 + 2,user.firstName,formatName(user)все законны. Например:

const user = {
    firstName: 'Zhang',
    lastName : 'Busong'
};

const elem = (
    <h1>Hello, {formatName(user)}</h1>
);
/*
这里的(),实际上是可选的,但是React推荐加入(),这样子就会被视为一个表达式,而不会导致
自动插入分号的问题
*/

ReactDOM.render(
    element,
    document.getElementById('app')
)

3. JSX — это тоже выражение

JSX сам по себе является выражением, поэтому его можно использовать, как и любое другое выражение, для присвоения значения переменной, в качестве аргумента функции, в качестве возвращаемого значения функции и т. д. Такие как:

function getGreeting(user) {
    if (user) {
        return <h1>Hello, {formatName(user)}</h1>
    }
    return <h1>Hello, Guest!</h1>;
}

Уведомление:1. В JSX не используйте кавычки при объявлении атрибутов.Если вы используете кавычки при объявлении атрибутов, они будут анализироваться как строки, а не как выражение, например:

<div firstName="{user.firstName}" lastName={user.lastName}></div>

После разбора можно получить:

<div firstName="{user.firstName}" lastName="Lau"></div>

Поэтому, когда нам нужно использовать строковый литерал, мы можем использовать кавычки, но если он должен быть проанализирован как выражение, мы не должны использовать кавычки. 2. В JSX некоторые имена свойств требуют специальной обработки. Такие какclassследует использоватьclassNameзаменять,tabindexзатем используйтеtabIndexзаменять. Это связано с тем, что JSX по своей природе ближе к JavaScript, аclassявляется зарезервированным словом в JavaScript. При этом следует использоватьcamelCaseчтобы назвать атрибут вместо использования именования атрибутов HTML 3. Сам JSX выполняет обработку против инъекций. Для тех HTML-кодов, которые не написаны явно, они не будут анализироваться в HTML DOM. ReactDOM будет рассматривать их как строки и преобразовывать их в строки до завершения рендеринга. Таким образом, это может предотвратить XSS-атака 4. Если тег JSX закрыт, то конец должен быть/>, Кроме того, теги JSX могут быть вложены друг в друга, что аналогично HTML.

4. Суть JSX

JSX компилируется babel, а babel фактически компилирует JSX вReact.createElement()передача. Следующий код JSX:

const element = (
    <h1 className="greeting">
        Hello, world!
    </h1>
);

эквивалентно следующему утверждению:

const elem = React.createElement(
    'h1',
    {className: 'greeting'},
    'Hello, world!'
);

React.createElement()Метод сначала выполнит некоторые проверки, чтобы избежать ошибок, а затем вернет объект, как в следующем примере:

const element = {
    type: 'h1',
    props: {
        className: 'greeting',
        children: 'Hello, world'
    }
}

Такой объект называетсяReact元素, который представляет все, что отображается на экране. React создает DOM, считывая эти объекты и синхронизируя данные и пользовательский интерфейс.

5. Рендеринг элемента

элемент(elements) — это наименьшая единица, из которой состоит приложение React.Элементы описывают то, что вы хотите видеть на экране, например:

const element = <h1>Hello, world</h1>;

В отличие от элементов DOM, элементы React — это чистые объекты, и их создание дешево. А React оптимизирует обработку и обновит только необходимые изменения в DOM. Кроме того, понятия элементов и компонентов не совпадают, а компоненты состоят из элементов.

6. Рендеринг элемента в DOM

В Реакции используйтеReactDOM.render()метод для рендеринга элементов React в DOM. Такие как:

ReactDOM.render(
    element,
    document.getElementById('root')
)

Элементы React неизменяемы, поэтому после создания элемента мы не можем изменить его содержимое или свойства. Элемент похож на кадр в анимации, он представляет, как выглядит пользовательский интерфейс в определенный момент времени. Если вам нужно использовать элементы для формирования изменяемого пользовательского интерфейса, вам нужно использоватьsetInterval, Такие как:

function tick() {
    const element = (
        <div>Now is {new Date().toLocaleTimeString()}</div>
    );
    ReactDOM.render(
        element,
        document.getElementById('root')
    );
}
setInterval(tick, 1000);

В реальной разработке большинство приложений React будут вызываться только один раз.ReactDOM.render(), поэтому лучше использовать有状态组件

7. Компоненты и реквизит

компоненты (component), чтобы иметь возможность разделить пользовательский интерфейс на независимые повторно используемые части, чтобы нам нужно было сосредоточиться только на создании каждой отдельной части. Концептуально компоненты похожи на функции: они принимают произвольные входные данные (называемые свойствами,Props), который возвращает элемент React. Есть два способа определить компоненты в React:函数定义а также类定义

1. Компонент определения функции

Это самый простой способ определить компоненты, точно так же, как написать функцию JS, например:

function Welcome (props) {
    return <h1>Hello, {props.name}</h1>;;
}

2. Компоненты определения класса

Вы также можете использовать классы ES6 для определения компонента, например:

class Welcome extends React.Component {
    render () {
        return <h1>Hello, {this.props.name}<h1>;
    }
}

таким образом по сравнению с函数定义более гибкий

3. Рендеринг компонентов

Раньше элементы React, с которыми мы сталкивались, просто отображали тег DOM, например:

const element = <div />

Однако элементы React также могут быть определены пользователем.组件,Такие как:

const element = <Welcome name="Tom" />

Свойство объявлено в компоненте приветствияname="Tom", и это свойство будет начинаться сprops.nameМетод передается компоненту следующим образом:

function Welcome (props) {
    return <h1>Hello, {props.name}</h1>;
}

На данный момент для следующего кода:

ReactDOM.render(
    <Welcome name="张不怂" />,
    document.getElementById('root')
)

в конце концов<h1>Hello, 张不怂</h1>способ подачи. В ходе этого процесса произошло следующее:

  • правильно<Welcome name="张不怂" />элемент называетсяReactDOM.render()богатый
  • Реагировать будет{ name: '张不怂' }Вызвать компонент Welcome в качестве аргумента реквизита
  • Добро пожаловать завершает рендеринг и возвращается<h1>Hello, 张不怂</h1>элемент
  • ReactDOM вычисляет минимальную стоимость обновления, а затем обновляет DOM.

4. Комбинированные компоненты

Компоненты являются составными. То есть внутри компонента можно ссылаться на другие компоненты, например:

function Welcome (props) {
    return <h1>Hello, {props.name}</h1>;
}

function App () {
    return (
        <div>
            <Welcome name="Tom" />
            <Welcome name="Jack" />
            <Welcome name="Mike" />
        </div>
    )
}

ReactDOM.render(
    <App />,
    document.getElementById('root')
)

Уведомление:В React компоненты должны возвращать单一Корневой элемент , поэтому компонент приложения должен использовать<div>Причина в упаковке этикетки. Следующий способ неверен (потому что он имеет 3 корневых элемента):

function App () {
    return (
        <Welcome name="Tom" />
        <Welcome name="Jack" />
        <Welcome name="Mike" />
    )
}

5. Свойства доступны только для чтения

Рассмотрим следующую ситуацию:

function sum (a, b) {
    return a + b;
}

Эта функция называется纯函数: он не изменяет свое собственное входное значение и всегда возвращает один и тот же результат для одного и того же ввода. Вопреки этому, это非纯函数,Такие как:

function withdraw (account, amount) {
    account.total -= amount;
}

非纯函数Входные параметры были изменены внутри функции. В React либо черезfunctionещеclassобъявить компонент, никто из нас не должен изменять его собственные свойства (props). Хотя React довольно гибок, у него также есть строгое правило:所有的React组件都必须像纯函数那样来使用它们的props

8. Состояние и жизненный цикл

использовать类定义组件Есть некоторые дополнительные преимущества, такие как наличие本地状态эта особенность. Ниже приводится类定义组件

class Clock extends React.Component {
    render () {
        return (
            <div>
                <h1>Hello, world!</h1>
                <h2>Now is {this.props.date.toLocaleTimeString()}</h2>
            </div>
        );
    }
}

Примечание:

  • 类名то есть组件名(Независимо от того, является ли это компонентом, определяемым функцией, или компонентом, определяемым классом, первая буква имени компонента должна быть написана с заглавной буквы и унаследована отReact.Component)
  • использоватьrender()метод для возврата содержимого, которое необходимо отобразить

1. Добавьте состояние в класс

Состояние принадлежит самому компоненту. Мы можем сделать это в конструкторе классаconstructorдля инициализации состояния, например:

constructor (props) {
    super(props)
    this.state = {
        date: new Date()
    }
}

Таким образом, мы можемrender()используется в функцииthis.state.xxxотноситься к государству

2. Жизненный цикл

В приложении часто бывает много компонентов. После уничтожения компонентов важно переработать и высвободить ресурсы, которые они занимают. существует时钟应用В примере нам нужно установить таймер при рендеринге в DOM в первый раз и очистить этот таймер после уничтожения соответствующего DOM. Итак, в данном случае React предоставляет нам удобные для нас функции-ловушки жизненного цикла. В React жизненный цикл делится на: 1)MountВставлен реальный DOM 2)Updateповторный рендеринг 3)UnmountПеремещено из реального DOM Соответственно, функции хука жизненного цикла:

  • componentWillMount
  • componentDidMount
  • componentWillUpdate(newProps, nextState)
  • componentDidUpdate(prevProps, prevState)
  • componentWillUnmount()

Кроме того, есть две специальные функции обработчика состояния:

  • componentWillReceiveProps(nextProps)Вызывается, когда загруженный компонент получает новые параметры
  • shouldComponentUpdate(nextProps, nextState)Вызывается, когда компонент определяет, следует ли повторно отображать

Следовательно, на основе функции ловушки жизненного цикла мы можем реализовать приложение часов следующим образом:

class Clock extends React.Component {
    constructor (props) {
        super(props);
        this.state = {
            date: new Date()
        }
    }
    tick () {
        this.setState({
            date: new Date()
        });
    }
    componentDidMount () {
        this.timerId = setInterval(() => {
            this.tick()
        }, 1000);
    }
    componentWillUnmount () {
        clearInterval(this.timerId);
    }
    render () {
        return (
            <div>Now is {this.state.date.toLocaleTimeString()}</div>
        );
    }
}

нужно знать, это: 1)render()непригодный для использованияstate, не следует объявлять вstateвнутри 2) нельзя использовать напрямуюthis.state.xxx = xxxспособ изменитьstateзначение, вы должны использоватьthis.setState(). Такие как:

setName () {
    this.setState({
        name: '张不怂'
    })
}

this.setState()автоматически перезапишетthis.stateсоответствующие свойства вrender()Перерендерить. 3)Обновления статуса могут быть асинхроннымиReact может объединять несколькоsetState()Вызовы объединяются в один вызов для повышения производительности. и из-заthis.propsа такжеthis.stateМогут обновляться асинхронно, поэтому на их значение не следует полагаться при расчете следующего состояния. В этом случае можно датьsetStateПередайте функцию, например:

this.setState((prevState, props) => ({
    counter: prevState.counter + props.increment
}));

9. Обработка событий

События элемента React похожи на элементы DOM, но есть некоторые отличия, такие как: 1) Использование событий реакцииcamelCaseимя(onClick) вместо всех строчных (onclick) 2) При использовании JSX передается дескриптор события, а не строка HTML, как показано ниже:

<button onclick="increment()">ADD</button>

Способ использования React описывается как:

<button onClick={increment}>ADD</button>

Еще одно отличие состоит в том, что в нативном DOM мы можем вернутьfalseчтобы предотвратить поведение по умолчанию, но это не работает в React, где его нужно явно использоватьpreventDefault()чтобы предотвратить поведение по умолчанию. Такие как:

function ActionLink () {
    function handleClick (e) {
        e.preventDefault();
        alert('Hello, world!');
    }

    return (
        <a href="#" onClick={handleClick}>Click Me</a>
    );
}

Здесь, в функции обратного вызова событияeventReact специально обработан (в соответствии со стандартом W3C), поэтому мы можем безопасно использовать его, не беспокоясь о проблемах кроссбраузерной совместимости.Уведомление:При использовании функций обратного вызова события нам нужно обратить особое вниманиеthisуказывает на проблему, потому что в ReactЗа исключением конструктора и функции-ловушки жизненного цикла, которая автоматически привязывает это как текущий компонент, остальные не будут автоматически привязываться.thisуказывает на текущий компонент, поэтому нам нужно обратить внимание на привязку этого, В общем, чтобы использовать обратные вызовы событий в объявленном классом компоненте, нам нужнобыть в составеconstructorЭто указывает на связанный метод обратного вызова в,Такие как:

class Counter extends React.Component {
    constructor (props) {
        super(props);
        this.state = {
            counter: 0
        }
        // 在这里绑定指向
        this.increment = this.increment.bind(this);
    }
    increment () {
        this.setState({
            counter: this.state.counter + 1
        });
    }
    render () {
        return (
            <div>
                The counter now is: {this.state.counter}
                <button onClick={this.increment}>+1</button>
            </div>
        );
    }
}

Конечно, у нас есть другой способ использоватьстрелочная функцияСвязывание указывает на использование实验性синтаксис инициализации свойств, например:

class Counter extends React.Component {
    increment: () => {
        this.setState({
            counter: this.state.counter + 1
        });
    }
    // ...
}

3) Передайте параметры, такие как обработчики событий Мы можем передать дополнительные параметры обработчику события двумя способами:

<button onClick={(e) => this.deleteRow(id, e)}>Delete Row</button>
<button onClick={this.deleteRow.bind(this, id)}>Delete Row</button>

Следует отметить, что при использовании стрелочных функций параметрыeПередаваться явно, а в случае с биндом явно передавать не нужно (параметрeбудет передан в качестве последнего параметра обработчику события)

10. Условный рендеринг

В React мы можем создавать различные компоненты для инкапсуляции нужной нам функциональности. Также мы можем рендерить только часть содержимого компонента исходя из состояния компонента, и для этого подготовлен условный рендеринг. В React мы можем писать условные операторы рендеринга так же, как мы пишем условные операторы в JavaScript, например:

function Greet(props) {
    const isLogined = props.isLogined;
    if (isLogined) {
        return <div>Hello !</div>;
    }
    return <div>Please sign in</div>;
}

ReactDOM.render(
    <Greet isLogined={true} />,
    document.getElementById('root')
);

Это будет отображать:

<div>Hello !</div>

1. Используйте переменные для хранения элементов

Мы также можем использовать переменные для хранения элементов, например:

function LogBtn(props) {
    var button;
    const isLogined = props.isLogined;
    if (isLogined) {
        button = <button>退出</button>
    } else {
        button = <button>登陆</button>
    }
    return <div>You can {button}</div>;
}

ReactDOM.render(
    <LogBtn isLogined={false} />,
    document.getElementById('root')
);

2. Рендеринг с помощью оператора &&

Обработано из-за синтаксиса JavaScript&&Природа оператора, мы также можем использовать оператор && для завершения условного рендеринга, например:

function LogBtn(props) {
    var button;
    const isLogined = props.isLogined;
    return (
        <div>Hello
        {!isLogined && (
            <button>请登陆</button>
        )}
        </div>
    )
}

когдаprops.isLoginedКогда false, он будет отображать:

<div>Hello <button>请登录</button></div>

3. Рендеринг с использованием тернарного оператора

Возможно, мы обнаружили, что JSX можно гибко использовать как выражение, поэтому мы также можем использовать тернарный оператор для рендеринга, например:

function LogBtn (props) {
    const isLogined = props.isLogined;
    return (
        <div>You can 
            <button>{isLogined ? '退出' : '登陆'}</button>
        </div>
    )
}

4. Заблокируйте рендеринг всего компонента

Иногда мы хотим, чтобы весь компонент не визуализировался, а только частично, тогда в этом случае мы можемrender()функция возвращаетnull, чтобы добиться желаемого эффекта, например:

function LogBtn (props) {
    const isLogined = props.isLogined;
    const isShow = props.isShow;
    if (isShow) {
        return (
            <div>You can 
                <button>{isLogined ? '退出' : '登陆'}</button>
            </div>
        )
    }
    return null;
}

Уведомление:возврат в компонентеnullНе повлияет на триггер жизненного цикла компонента, напримерcomponentWillUpdateа такжеcomponentDidUpdateвсе равно будут называть

11. Рендеринг списка и ключи

В JavaScript мы можем использоватьmap()функция для работы со списком массивов, например:

const numbers = [1, 2, 3, 4, 5];
const doubled = numbers.map(number => number*2);
console.log(doubled); // 得到[2, 4, 6, 8, 10]

Точно так же в React мы также можем использоватьmap()Чтобы сделать список, например:

const numbers = [1, 2, 3, 4, 5];
const listItems = numbers.map(number => {
    return (
        <li>{number}</li>
    )
});

ReactDOM.render(
    <ul>{listItems}</ul>,
    document.getElementById('root')
)

Это даст:

<ul><li>1</li>
    <li>2</li>
    <li>3</li>
    <li>4</li>
    <li>5</li>
</ul>

Конечно, мы также можем улучшить инкапсуляцию, например:

function NumberList (props) {
    const numbers = props.numbers;
    const listItems = numbers.map(number => {
        return (
            <li>{number}</li>
        )
    });

    return <ul>{listItems}</ul>
}

Когда мы запустим приведенный выше код, мы найдем приглашение консоли:Each child in an array or iterator should have a unique "key" prop, поэтому нам нужно присвоить каждому элементу спискаkey, чтобы решить эту проблему, вообще говоря, мы можем использовать следующие методы для обеспеченияkey:

  • Используйте идентификатор самого элемента данных, например<li key={item.itemId}>
  • Использовать индексную подписку (index),Такие как:
const listItems = numbers.map((number, index) => {
    <li key={index}>{number}</li>
});

Но React не рекомендует использовать индексированные индексы в списках, которые нужно переупорядочивать, потому что это будет очень медленно.

Уведомление:Ключ необходимо использовать только тогда, когда одноуровневые элементы элемента отличаются друг от друга.Ключ не обязательно должен быть уникальным в глобальном масштабе, а должен быть уникальным только при различении друг друга в массиве. Роль ключа состоит в том, чтобы дать React подсказку, и она не передается компоненту. Если нам нужно такое же значение в компоненте, мы можем передать его под другим именем, например:

const content = posts.map(post => (
    <Post key={post.id} id={post.id} title={post.title} />
));

12. Формы

Формы отличаются от других элементов DOM в React, потому что элементы формы созданы для хранения некоторого внутреннего состояния. Формы в React немного отличаются от форм в HTML.

1. Контролируемые компоненты

HTML,<input>,<textarea>,<select>Эти элементы формы сохраняют свое собственное состояние и обновляются в зависимости от ввода пользователя. Однако в React изменяемое состояние обычно хранится в компоненте.this.state, и может использоваться толькоsetState()Метод обновления, например:

class NameForm extends React.Component {
    constructor (props) {
        super(props);
        this.state = {
            value: ''
        }
        this.handleChange = this.handleChange.bind(this);
        this.handleSubmit = this.handleSubmit.bind(this);
    }
    handleChange (event) {
        this.setState({
            value: event.target.value
        });
    }
    handleSubmit (event) {
        alert('Your name is '+this.state.value);
        event.preventDefault();
    } 
    render () {
        return (
            <form onSubmit={this.handleSubmit}>
            Name: <input type="text" value={this.state.value} onChange={this.handleChange} />
            <input type="submit" value="Submit" />
            </form>
        )
    }
}

В отличие от HTML, Reacttextareaне нужно писать как<textarea></textarea>форме, но пишется как<textarea value="" ... />форма может быть. И для HTML вselectэтикетка, обычно:

<select>
    <option value="A">A</option>
    <option value="B" selected>B</option>
    <option value="C">C</option>
</select>

Но в React нет необходимости выбиратьoptionприсоединитьсяselectedИ нужно только пройти значение, он автоматически выберет соответствующую опцию в соответствии со значением, таким как:

<select value="C">
    <option value="A">A</option>
    <option value="B">B</option>
    <option value="C">C</option>
</select>

Тогда, как и в приведенном выше примере, тот, где находится Coptionбудет выбран

2. Решения для нескольких входов

Обычно форма имеет несколько входов, если мы добавим события обработчика для каждого входа, это будет очень громоздко. Хорошим решением является использование имени, а затемevent.target.nameвыбирать, что делать. Такие как:

class Form extends React.Component {
    constructor (props) {
        super(props);
        this.state = {
            name: '',
            gender: '男',
            attend: false,
            profile: ''
        };
        this.handleInputChange = this.handleInputChange.bind(this);
        this.handleSubmit = this.handleSubmit.bind(this);
    }
    handleInputChange (event) {
        const target = event.target;
        const value = target.type==='checkbox' ? target.checked : target.value;
        const name = target.name;
        this.setState({
            [name]: value
        });
    }
    handleSubmit (event) {
        this.setState({
            profile: `姓名:${this.state.name},${this.state.gender},${this.state.attend ? '参加' : '不参加'}活动`
        });
        event.preventDefault();
    } 
    render () {
        return (
            <form>
            <p>姓名:<input name="name" value={this.state.name} onChange={this.handleInputChange} /></p>
            <p>性别:
                <select name="gender" value={this.state.gender} onChange={this.handleInputChange}>
                    <option value="男">男</option>
                    <option value="女">女</option>
                </select>
            </p>
            <p>是否参加:<input name="attend" type="checkbox" onChange={this.handleInputChange} checked={this.state.attend} /></p>
            <input type="submit" value="Submit" onClick={this.handleSubmit} />
            <p>您的报名信息:{this.state.profile}</p>
            </form>
        )
    }
}

3. Неконтролируемые компоненты

В большинстве случаев используют受控组件Предпочтительна реализация формы, а в контролируемом компоненте данные формы обрабатываются компонентом React. Если вы хотите, чтобы данные формы обрабатывались DOM (то есть данные хранились не в состоянии React, а в DOM), вы можете использовать非受控组件,использовать非受控组件, вы можете избавиться от необходимости писать обработчики событий для каждого обновления состояния, использоватьrefможет быть достигнуто, например:

class NameForm extends React.Component {
    constrcutor(props) {
        super(props)
    }
    handleSubmit(event) {
        console.log('A name was submitted: ', this.input.value)
        event.preventDefault()
    }
    render() {
        return (
            <form onSubmit={this.handleSubmit}>
                <label>
                Name: <input type="text" ref={input => this.input = input} />
                </label>
                <input type="submit" value="submit" />
            </form>
        )
    }
}

для非受控组件, если вы хотите указать значение по умолчанию, вы можете использоватьdefaultValue,Такие как:

<input type="text" defaultValue="Hello" ref={input => this.input = input} />

соответствующий,type="checkbox"а такжеtype="radio", затем используйтеdefaultChecked

13. Улучшение статуса

Когда нескольким компонентам необходимо совместно использовать данные о состоянии, можно использовать методы повышения состояния. Основная идея состоит в том, чтобы извлекать данные в ближайший общий родительский компонент, родительский компонент управляет состоянием (state), а затем передает их дочернему компоненту через свойства (props). Например, для реализации компонента конвертации валюты это может быть так:

1. Сначала определите функцию преобразования

function USD2RMB (amount) {
    return amount * 6.7925;
}

function RMB2USD (amount) {
    return amount * 0.1472;
}

function convert (amount, typeFn) {
    return typeFn(amount);
}

2. Определите компоненты

我们希望在RMB的输入表单上上输入的时候,USD的输入表单上的数值也同步更新,这种情况下,如果RMB组件自己管理自己的状态,是很难以实现的,因此,我们需要让这个状态提升自父组件进行管理。 следующим образом:

class CurrencyInput extends React.Component {
    constructor (props) {
        super(props)
        this.handleChange = this.handleChange.bind(this)
    }
    handleChange (event) {
        this.props.onInputChange(event.target.value)
    }
    render () {
        const value = this.props.value
        const type = this.props.type
        return (
            <p>{type}: <input type="text" value={value} onChange={this.handleChange} /></p>
        );
    }
}

Наконец, определите общий родительский компонент следующим образом:

class CurrencyConvert extends Component {
    constructor (props) {
        super(props);
        this.state = {
            type: 'RMB',
            amount: 0
        }
        this.handleRMBChange = this.handleRMBChange.bind(this);
        this.handleUSDChange = this.handleUSDChange.bind(this);
    }
    handleRMBChange (amount) {
        this.setState({
            type: 'RMB',
            amount
        });
    }
    handleUSDChange (amount) {
        this.setState({
            type: 'USD',
            amount
        });
    }
    render () {
        const type = this.state.type;
        const amount = this.state.amount;
        const RMB = type==='RMB' ? amount : convert(amount, USB2RMB);
        const USD = type==='USD' ? amount : convert(amount, RMB2USB);
        return (
            <div>
                <p>Please Input:</p>
                <CurrencyInput type="RMB" value={RMB} onInputChange={this.handleRMBChange} />
                <CurrencyInput type="USD" value={USD} onInputChange={this.handleUSDChange} />
            </div>
        );
    }
}

14. Композиция против наследования

React предпочитает композицию больше, чем наследование. Для некоторых сценариев использования React дает следующие рекомендации:

1. Отношения включения

Когда родительский компонент не знает, каково возможное содержимое дочернего компонента, его можно использоватьprops.children,Такие как:

function Article (props) {
    return (
        <section>
            <aside>侧边栏</aside>
            <article>{props.children}</article>
        </section>
    );
}

function App () {
    return (
        <Article>这是一篇文章</Article>
    );
}

Это будет отображать:

<section>
    <aside>侧边栏</aside>
    <article>这是一篇文章</article>
</section>

Мы также можем настроить имя, потому что JSX фактически будет преобразован в допустимое выражение JS, поэтому мы также можем иметь:

function Article (props) {
    return (
        <section>
            <aside>{props.aside}</aside>
            <article>{props.children}</article>
        </section>
    );
}

function App () {
    return (
        <Article aside={
            <h1>这是一个侧栏</h1>
        }>这是一篇文章</Article>
    );
}

Это будет отображать:

<section>
    <aside><h1>这是一个侧栏</h1></aside>
    <article>这是一篇文章</article>
</section>

2. Когда использовать наследование?

На веб-сайте Facebook используются тысячи компонентов, но было доказано, что не существует ситуаций, для решения которых требуется использование наследования. Атрибуты и композиция предоставляют нам четкий и безопасный способ настройки стиля и поведения компонентов.Компоненты могут принимать произвольные элементы, в том числе: базовые типы данных, элементы React и функции. Если функциональность, независимая от пользовательского интерфейса, должна повторно использоваться между компонентами, ее следует выделить в отдельный модуль JavaScript, чтобы можно было импортировать и использовать функции, объекты, классы без расширения компонентов.

Если вы считаете, что это полезно для вас, пожалуйста, нажмите

отличный,

不妨再点个关注,不迷路,下一篇关于redux的明天就发! ! ~