Если вы только начинаете с Реагировать, я настоятельно рекомендую следующие Pete Hunt's advice:
Вы будете знать, когда вам нужно Flux. Если вы не уверены, что вам это нужно, вам это не нужно.
Лучшее, что нужно сделать, это начать с Реагирования самостоятельно и управлять состоянием приложения, используя локальный state
, который поставляется с каждым из ваших компонентов.
Когда вы обнаружите, что вам придётся передать данные обратно родительским компонентам, добавьте Flux в микс и перепишите свои компоненты с состоянием, чтобы вместо этого использовать магазины Flux.
Мы рассмотрим, как решить написать упрощенную версию компонента ответа StackOverflow в качестве приложения React снизу вверх.
Заметьте, я сказал Реагировать приложение, не Реагировать компонент. Это потому, что нет технических различий. Приложение React - это большой компонент React, состоящий из множества меньших.
идентификации компонентов
После того, как у вас есть интерфейс для приложения (что-нибудь из каркасных в HTML/CSS) вы можете визуально подразделить их на работу, как они подходят друг к другу, как Реагировать компоненты.
Нет никаких жестких и быстрых правил о том, как именно вы решаете, что должно или не должно быть его собственным компонентом, но вы почувствуете это больше, когда вы это сделаете.
- является
<Answer />
- является
<Votes />
- является
<AnswerText />
- является
<AnswerActions />
Поскольку мы строим снизу вверх, мы должны начать с реализации каждого из дочерних компонентов и тестирования, что они работают в одиночку.
На этом этапе жизненного цикла разработки мы просто напишем статическую разметку для каждого компонента. Не нужно думать о реквизитах или состоянии.
Мы можем использовать синтаксис компонента без состояния, чтобы начать работу с идентифицированными компонентами. Вот пример того, как мы могли бы написать компонент <Votes />
.
function Votes() {
return (
<div>
<a>▲</a>
<strong>0</strong>
<a>▼</a>
</div>
);
}
Конечно, это не делает ничего, но это позволяет нам начать сочинять наши компоненты, чтобы получить чувство для структуры приложения.
Мы можем сделать это в DOM, чтобы проверить, что он работает в любое время.
ReactDOM.render(<Votes />, document.getElementById('app'));
После того, как вы завершили реализацию статических версий других компонентов, вы можете поместить их вместе, чтобы создать родитель <Answer />
компонента.
function Answer() {
return (
<div>
<Votes />
<AnswerText />
<AnswerActions />
</div>
);
}
потока данных Дизайн
Следующая вещь, которую нужно сделать, это выяснить, как потоки данных через приложения.
На данный момент мы можем создать несколько фиктивных данных в виде объекта ответа, который выглядит примерно так:
{
"id": 0,
"votes": 0,
"text": "This is an answer"
}
Первоначально мы можем оказать <Answer />
составляющую, передавая этот объект ответа на него в качестве опоры ,
<Answer answer={answer} />
Теперь это то, что компоненты выполняют передачу соответствующих данных своим детям.
Очевидно, что не каждому ребенку нужны все данные, поэтому нам нужно будет решить, какие данные идут туда. Давайте обновим наш компонент <Answer />
.
function Answer(props) {
var answer = props.answer;
return (
<div>
<Votes id={answer.id} count={answer.votes} />
<AnswerText text={answer.text} />
<AnswerActions id={answer.id} />
</div>
);
}
The <Votes />
потребности компонентных знать текущее количество голосов, и он также должен знать id
ответа, так что он может общаться изменения на сервер.
Компонент <AnswerText />
просто отображает блок текста, так что это все, что нам нужно передать.
Наконец, компонент <AnswerActions />
отображает список ссылок, которые позволяют пользователю выполнять какое-либо действие (обмениваться, редактировать, отмечать) в ответе. Этот компонент также нуждается в ответе id
, чтобы он мог связываться с сервером.
Теперь мы должны обновить эти дочерние компоненты в свою очередь, чтобы использовать эти новые динамические значения вместо статических значений, которые мы использовали вначале. Мы рассмотрим компонент <Votes />
, чтобы это произошло.
function Votes(props) {
var urls = {
upvote: '/api/answers/' + props.id + '/upvote',
downvote: '/api/answers/' + props.id + '/downvote'
};
return (
<div>
<a href={urls.upvote}>▲</a>
<strong>{props.votes}</strong>
<a href={urls.downvote}>▼</a>
</div>
);
}
Теперь наш компонент голосования будет сделать запрос HTTP на соответствующую конечную точку, когда мы нажимаем на кнопках голосования, однако, мы бы лучше сделать это обновление без перезагрузки и повторного рендеринга всего приложения.
Идентифицировать Stateful Компоненты
Заключительная часть процесса разработки компонента, чтобы идентифицировать компоненты с сохранением состояния. Эти компоненты имеют движущиеся части и данные, которые будут меняться в течение всего срока службы приложения.
Каждый раз, когда состояние внутри компонента изменяется, весь компонент повторно отображается. Мы можем пересмотреть каркасы, чтобы увидеть, какие из наших компонентов должны управлять изменяющимися данными.
Это приложение имеет только один компонент с сохранением состояния (), и это `. Когда мы нажимаем на одну из стрелок, нам нужно обновить номер, чтобы отобразить новый счетчик.
Это единственный из наших компонентов, который когда-либо нуждается в повторной обработке.
Это означает, что нам нужно будет обновить компонент, чтобы использовать синтаксис React's createClass
. Это позволяет ему управлять своим собственным состоянием.
var Votes = React.createClass({
getInitialState: function() {
return { votes: this.props.votes };
},
upvote: function() {
var newVotes = this.state.votes + 1;
this.setState({
votes: newVotes
});
},
downvote: function() {
var newVotes = this.state.votes - 1;
this.setState({
votes: newVotes
});
},
render: function() {
return (
<div>
<a onClick={this.upvote}>▲</a>
<strong>{this.state.votes}</strong>
<a onClick={this.downvote}>▼</a>
</div>
);
}
});
Я немного подпрыгнул из пушки и внедрил полный компонент, но, надеюсь, вы получите эту идею.
Сначала мы используем getInitialState
создать какое-то состояние, чтобы представить начальное число голосов в компоненте.
Далее мы реализуем и downvote
методы компонентов, которые обновляют состояние компонента.
Наконец, мы повторно реализуем метод рендеринга ранее, но стрелки запускают новые методы компонентов, а не запросы страниц.
Каждый раз, когда мы делаем вызов setState
, React будет повторно вынести компонент. Надеюсь, вы можете понять, почему мы помещаем состояние в компонент <Votes />
, а не в компонент <Answer />
. Было бы безумным перерисовать текст ответа и действия, только потому, что голоса изменились.
Flux It Up
После того, как мы определили и реализовать все наши сохраняющих состояние компонентов, мы можем начать двигаться их состояние вне в Flux магазинах.
Скорее всего, что реальное приложение будет иметь <AnswerStore />
, чем <VoteStore />
, так что это будет реализовано нами. На данный момент мы просто будем насмехаться над нашими данными.
var AnswerStore = {
_listeners: [],
_answers: {
"0": {
"id": 0,
"votes": 0,
"text": "This is an answer"
}
},
get: function(id) {
return this._answers[id];
},
update: function(id, update) {
var answer = this.get(id);
var updatedAnswer = Object.assign({}, answer, update);
this._answers[id] = updatedAnswer;
this.emit();
},
listen: function(f) {
this._listeners.push(f);
},
emit: function() {
this._listeners.forEach(function(f) {
f();
});
}
};
В этом примере я написал довольно универсальный магазин, который содержит данные, предоставляет простые обработчик для прослушивания моделирования изменений и, наконец, предоставляет методы для мутируют данные в хранилище.
Важно, чтобы наш метод update
рассматривал индивидуальные ответы как неизменяемые в этом приложении, в противном случае мы рискуем изменить объект, к которому ссылаются другие части приложения, в результате чего объект изменяется под ними. Мы используем Object.assign
для создания нового объекта каждый раз, исходя из старого.
Следующее, что нам нужно сделать, это настроить некоторые обработчики действий для этого магазина.
dispatcher.register(function(action) {
switch(action.type) {
case 'UPVOTE':
var votes = ActionStore.get(action.id);
ActionStore.update(action.id, { votes: votes + 1 });
break;
case 'DOWNVOTE':
var votes = ActionStore.get(action.id);
ActionStore.update(action.id, { votes: votes - 1 });
break;
}
});
Это просто провода метод обновления для двух действий, называемых 'UPVOTE'
и 'DOWNVOTE'
Теперь мы связываем Flux нашего <AnswerComponent />
который должен быть переписано в длинной форме.
var Answer = React.createClass({
getInitialState: function() {
return { answer: {} };
},
componentWillMount: function() {
this.update();
AnswerStore.listen(this.update);
},
update: function() {
var id = this.props.id;
this.setState({ answer: AnswerStore.get(id) });
},
render: function() {
var answer = this.state.answer;
return (
<div>
<Votes id={answer.id} count={answer.votes} />
<AnswerText text={answer.text} />
<AnswerActions id={answer.id} />
</div>
);
}
});
В нашем componentWillMount
методе мы извлекаем наши исходные данные для магазина, а затем настроить слушатель на магазине, который извлекает и обновляет состояние компоненты, при изменении магазина.
И, наконец, нам нужен способ отправки соответствующих действий с нашего компонента <Votes />
.
Самый популярный способ сделать это с создателями действий. Создатель действия - это функция, которая принимает некоторые данные в качестве параметров, затем упаковывает их и отправляет их как действие.
var Actions = {
upvote: function(id) {
dispatcher.dispatch({
type: 'UPVOTE',
id: id
});
},
downvote: function(id) {
dispatcher.dispatch({
type: 'DOWNVOTE',
id: id
});
}
};
Тогда мы называем эти действия внутри нашего <Votes />
компонента (который может стать лицом без гражданства снова).
function Votes(props) {
var id = props.id;
return (
<div>
<a onClick={Actions.upvote.bind(null, id)}>▲</a>
<strong>{props.votes}</strong>
<a onClick={Actions.downvote.bind(null, id)}>▼</a>
</div>
);
}
Этот компонент теперь использует создателей действия для отправки действий для нашего хранилища (ов) Flux.
Если мы посмотрим на поток данных через наше приложение, мы можем видеть, что мы имеем теперь однонаправленный цикл, а не дерево.
<Answer />
компонент проходит id
вниз к <Votes />
компонента.
- Компонент
<Votes />
отправляет уведомление об этом, используя id
.
AnswerStore
обрабатывает действие и испускает изменение.
- Компонент
<Answer />
слышит обновление и обновляет его состояние, перерисовывая его дочерние элементы.
Это jsfiddle этой демонстрационной заявки.
Scale Up
Это очень простой компонент, который обрабатывает только небольшое количество потоков данных и даже меньше состояния приложения, однако, этого достаточно, чтобы показать вам, как составить Реагировать компонент, и это все, что вам нужно создайте приложение React.
Предположим, мы применяли вопрос StackOverflow как приложение React.
function App() {
return (
<Page>
<Navigation />
<SideBar>
<MetaDetails />
<Ads />
<RelatedQuestions />
</SideBar>
<Question />
<AnswerList />
<AnswerEditor />
<Footer />
</Page>
);
}
Это может показаться сложной приложения, но вы можете разбить его и выразить его в качестве отдельных компонентов, то вы можете реализовать и протестировать компоненты по отдельности, так же, как мы делали здесь и привести их в целом, чтобы сформировать комплексное применение.
Не Над осложнять
Для наиболее простых Реагировать приложения, такие как этот, поток не на самом деле необходимо. Стоит помнить, что React был выпущен за год до Flux, и все же он был принят многими разработчиками независимо.
Конечно, я действительно рассматривал структурирование и реализацию компонентов здесь. Принятие приложения из каркасов в развертывание - гораздо более сложный процесс, и в одном ответе он не может быть подробно рассмотрен. Со временем, вы, вероятно, также хотят, чтобы узнать о:
- управления пакетами и зависимостями
- Модуль Упаковщики
- маршрутизации
- Hot
Перезагрузка
- ES6/Babel
- Redux
- Опорная сторона сервера
- Неизменяемые данные
- Встроенные стили
- Реле/Falcor/GraphQL
Это займет некоторое время, чтобы получить этот список вещей, хитрость заключается в том, чтобы не спешить. Естественно, не перенастраивайте свой существующий проект, пока не найдете причины, по которым эти решения существуют.
Думаю react-howto лучший путеводитель там.Несмотря на то, что он не очень подробен, он связан с множеством хороших ресурсов, и, самое главное, он дает упрямое руководство к порядку, в котором вы должны изучить эти технологии на своем пути к тому, чтобы стать компетентным разработчиком ReactJS.
Какую добавленную стоимость вы получаете, введя как Angular, так и ReactJS? – christopher
Ну, мне было просто интересно, потому что Reacjs похож на вид. В то время как у Angular есть контроллер просмотра модели и т. Д., Просто глядя, чтобы структурировать код хорошо –
У меня есть этот jsfiddle, но он получил ошибку и не передавал реагирующие компоненты. Что не так? https://jsfiddle.net/5syaz4La/2/ –