
Содержание статьи
автор Сунил Сандху
Воспользовавшись Vue на моем нынешнем рабочем месте я достаточно ясно понимал, как это все работает. Однако мне было интересно узнать, какой была трава по ту сторону забора – трава в этом сценарии была React.
Я прочитал документы React и просмотрел несколько обучающих видео, и, хотя они были замечательными, я действительно хотел знать, насколько они отличаются Отреагировать был из Vue.
Под «разным» я не имел в виду вещи, например, были ли они оба виртуальные DOMS или как они отображали страницы. Я хотел, чтобы кто-то удосужился объяснить код и рассказать мне, что происходит! Я хотел найти статью, которая бы уделила время, чтобы объяснить эти отличия, чтобы кто-то новый Vue или Отреагировать (или веб-разработка в целом) может лучше понять отличия между ними.
Но я не смог найти ничего, что боролось бы с этим. Так что я понял, что мне придется идти дальше и построить это самому, чтобы увидеть сходство и отличие. Делая это, я думал, что задокументирую весь процесс, чтобы наконец-то появилась статья об этом.

Я решил попытаться создать достаточно стандартную программу To Do, позволяющую пользователю добавлять и удалять элементы из списка. Обе программы были созданы по умолчанию CLI (create-react-app для Отреагироватьи vue-cli для Vue). CLI, кстати, означает интерфейс командной строки. ?
Во всяком случае, это вступление длиннее, чем я ожидал. Давайте начнем с краткого обзора, как выглядят две программы:

Код CSS для обеих программ абсолютно одинаков, но есть отличия в том, где они расположены. Имея это в виду, давайте далее посмотрим на структуру файлов обеих программ:

Вы увидите, что их структуры тоже почти идентичны. Единственное отличие здесь заключается в том, что программа React имеет три файла CSS, в то время как программа Vue не имеет ни одного. Это потому, что в приложении create-react-app, компонент React будет иметь сопроводительный файл для хранения стилей, тогда как Vue CLI использует всеобъемлющий подход, когда стили объявляются внутри фактического файла компонента..
В конце концов они оба достигают одного и того же, и нельзя сказать, что вы не можете продолжить и структурировать свой CSS по-разному в React или Vue. Это действительно сводится к личным предпочтениям — вы услышите много обсуждений от сообщества разработчиков по поводу того, как должен быть структурирован CSS. Мы просто придерживаемся структуры, изложенной в обоих CLI.
Но прежде чем идти дальше, давайте быстро посмотрим, как выглядят типичные компоненты Vue и React:

Теперь это не так, давайте перейдем к мельчайшим деталям!
Как мы изменяем данные?
Но прежде, что мы вообще подразумеваем под «мутацией данных»? Звучит немного технически, не правда ли? В основном это означает только изменение данных, которые мы сохранили. Если бы мы хотели изменить значение имени человека с Джона на Марк, мы бы «изменили данные».
В этом состоит ключевое отличие между React и Vue. В то время как Vue по сути создает объект данных, где данные можно свободно обновлять, React создает объект состояния, где для обновления нужно немного больше работать..
Теперь React реализует дополнительную работу с полным основанием, и мы рассмотрим это чуть позже. Но сначала давайте посмотрим на данные объект с Vue и государство объект с React:


Итак, вы можете увидеть, что мы передали одинаковые данные в оба, но они просто сказываются по-разному. Поэтому передача исходных данных в наши компоненты очень похожа. Но, как мы уже упоминали, то, как мы собираемся изменить эти данные, отличается между фреймворками.
Скажем, у нас есть элемент данных под названием name: ‘Sunil’
.
В Vue мы ссылаемся на это, вызывая this.name
. Мы также можем обновить это, позвонив по телефону this.name = ‘John’
. Это изменило бы мое имя Джону. Я не уверен, что чувствую, когда меня зовут Джоном, но все бывает! ?
В React мы бы ссылались на ту же часть данных, вызывая this.state.name
. Ключевое отличие здесь состоит в том, что мы не можем просто писать this.state.name = ‘John’
, потому что React имеет ограничения, чтобы предотвратить такое легкое, беззаботное создание мутаций. Поэтому в React мы бы написали что-то вроде this.setState({name: ‘John’})
.
Хотя это, в сущности, делает то же самое, что мы достигли в Vue, есть дополнительная часть записи, поскольку Vue по сути объединяет свою собственную версию setState по умолчанию всякий раз, когда часть данных обновляется.
Итак, коротко, React требует setState, а затем обновленных данных внутри него, тогда как Vue делает предположение, что вы хотели бы это сделать, если бы вы обновляли значение внутри объекта данных.
Почему React вообще беспокоится об этом, и почему setState вообще нужен? Давайте передадим это Реванту Кумару для объяснения:
«Это потому, что React хочет повторно запустить определенные хуки жизненного цикла, [such as] componentWillReceiveProps, shouldComponentUpdate, componentWillUpdate, render, componentDidUpdate, когда состояние меняется. Он будет знать, что состояние изменилось, когда вы вызываете функцию setState. Если вы напрямую мутировали состояние, React пришлось бы выполнить гораздо больше работы, чтобы отслеживать изменения и какие крючки жизненного цикла запускать и т.д. Потому, чтоб сделать его обычным, React употребляет setState».

Теперь, когда у нас нет мутаций, давайте перейдем к тонкостям, взглянув на то, как мы будем добавлять новые элементы в обе наши программы To Do.
Как мы создаем новые задачи?
Отреагировать:
createNewToDoItem = () => {
this.setState( ({ list, todo }) => ({
list: [
...list,
{
todo
}
],
todo: ''
})
);
};
Как React сделал это?
В React наше поле ввода имеет атрибут под названием значение. Это значение автоматически обновляется благодаря использованию нескольких объединяемых функций, чтобы создать что-то, что очень напоминает двухсторонняя привязка (Если вы никогда не слышали об этом раньше, есть более подробное объяснение в Как Vue это сделал раздел после этого). Мы создаем эту форму двустороннего связывания, имея дополнительную прослушиватель событий onChange прикреплен к введение поле.
Давайте быстро посмотрим на введение поле, чтобы вы могли увидеть, что происходит:
<input type="text"
value={this.state.todo}
onChange={this.handleInput}/>
Функция handleInput запускается при каждом изменении значения поля ввода. Он обновляет сделать который находится внутри объекта состояния, установив для него то, что находится в поле ввода. Эта функция выглядит так:
handleInput = e => {
this.setState({
todo: e.target.value
});
};
Теперь, когда пользователь нажимает кнопку + кнопку на странице, чтобы добавить новый элемент, createNewToDoItem
функция по существу запускает this.setState и передает ему функцию.
Эта функция принимает два параметра, первый – это целое list
массив из объекта состояния, второй – это todo
(который обновляется с помощью handleInput
функция). Затем функция возвращает новый объект, содержащий все list
от предыдущего, а затем добавляет todo
в конце его. Весь список добавляется с помощью оператора распространения (Google это если вы не видели этого раньше — это синтаксис ES6).
Наконец-то мы поставили todo
к пустой строке, которая автоматически обновляет значение внутри введение поле.
Vue:
createNewToDoItem() {
this.list.push(
{
'todo': this.todo
}
);
this.todo = '';
}
Как Vue сделал это?
В Vue наш введение поле имеет дескриптор под названием v-модель. Это позволяет нам делать что-то известное как двухсторонняя привязка. Давайте просто быстро посмотрим на наше поле ввода, а затем объясним, что происходит:
<input type="text" v-model="todo"/>
V-Model увязывает ввод этого поля с ключом, который мы имеем в нашем объекте данных под названием toDoItem. Когда страница загружается, мы имеем toDoItem
установить пустую строку, как таковую: todo: ‘’
. Если бы там уже были некоторые данные, например todo: ‘add some text here’
наше поле ввода будет загружено из добавьте сюда текст уже внутри поля ввода.
В любом случае, возвращаясь к пустой строке, любой текст, который мы вводим в поле ввода, привязывается к значению для todo
. Это фактически двусторонняя привязка (поле ввода может обновлять объект данных, а объект может обновлять поле ввода).
Так что оглядываясь на createNewToDoItem()
блок кода из предыдущего, мы видим, что мы нажимаем содержимое todo
в list
массив а затем обновить todo
к пустой строке.
Как удалить из списка?
Отреагировать:
deleteItem = indexToDelete => {
this.setState(({ list }) => ({
list: list.filter((toDo, index) => index !== indexToDelete)
}));
};
Как React сделал это?
Итак, в то время как функция deleteItem расположена внутри ToDo.jsя очень легко мог сделать ссылку на это внутри ToDoItem.js сначала передав deleteItem()
функционировать как опора <ToDoIte
m/> как таковой:
<ToDoItem deleteItem={this.deleteItem.bind(this, key)}/>
Это передает функцию вниз, чтобы сделать ее доступной для ребенка. Вы увидите, что мы также обязываем this
а также передачу ключевого параметра, поскольку ключ – это то, что функция собирается использовать, чтобы различать какой ToDoItem мы стараемся удалить при нажатии. Затем внутри ToDoItem компонент, мы делаем следующее:
<div className=”ToDoItem-Delete” onClick={this.props.deleteItem}>-</div>
Все, что мне нужно было сделать, чтобы ссылаться на функцию, находящуюся внутри родительского компонента, это ссылка this.props.deleteItem
.
Vue:
onDeleteItem(todo){
this.list = this.list.filter(item => item !== todo);
}
Как Vue сделал это?
У Vue нужен немного другой подход. По сути, здесь мы должны сделать три вещи:
Во-первых, для элемента, который мы хотим вызвать функцию:
<div class=”ToDoItem-Delete” @click=”deleteItem(todo)”>-</div>
Затем мы должны создать функцию emit как метод внутри дочернего компонента (в этом случае, ToDoItem.vue), который выглядит так:
deleteItem(todo) {
this.$emit('delete', todo)
}
Наряду с этим, вы заметите, что мы действительно ссылаемся на a функция когда мы добавляем ToDoItem.vue внутри ToDo.vue:
<ToDoItem v-for="todo in list"
:todo="todo"
@delete="onDeleteItem" // <-- this :)
:key="todo.id" />
Это то, что известно как а пользовательский прослушивающий события. Он прослушивает любой случай, когда излучение запускается с помощью строки ‘delete’
. Если он слышит это, он запускает вызванную функцию onDeleteItem
. Эта функция находится внутри ToDo.vue, а не ToDoItem.vue. Как мы обсуждали ранее, он просто фильтрует todo
массив внутри в data
объект чтобы удалить элемент, на который было нажато.
Здесь также следует отметить, что в примере Vue я мог бы просто написать файл $emit
часть внутри @click
слушатель как таковой:
<div class=”ToDoItem-Delete” @click=”$emit(‘delete’, todo)”>-</div>
Это снизило бы количество шагов вниз с 3 до 2, и это просто зависит от личных предпочтений.
Кратко, дочерние компоненты в React будут иметь доступ к родительским функциям через this.props
(при условии, что вы передаете реквизиты вниз, что является достаточно стандартной практикой, вы встретите это много раз в других примерах React). У Vue, с другой стороны, вы должны выдавать события от ребенка, которые обычно собираются внутри родительского компонента.
Как мы передаем слушателей?
Отреагировать:
Прослушивание событий для простых вещей, таких как события кликов, просты. Вот пример того, как мы создали событие клика для кнопки, создающей новый элемент ToDo:
<div className=”ToDo-Add” onClick={this.createNewToDoItem}>+</div>.
Здесь очень просто, и почти так, как мы бы обрабатывали встроенные onClick
с ванильным JS. Как упоминалось в разделе Vue, настроить прослушиватель событий для обработки всякий раз, когда нажималась кнопка ввода, потребовалось чуть больше времени. Это, по сути, требовало onKeyPress
событие, которое будет обрабатывать входной тэг, как:
<input type=”text” onKeyPress={this.handleKeyPress}/>.
Эта функция, в сущности, вызывала createNewToDoItem
функция каждый раз, когда она распознает, что была нажата клавиша «enter», как таковая:
handleKeyPress = (e) => {
if (e.key === ‘Enter’) {
this.createNewToDoItem();
}
};
Vue:
У Vue это очень просто. Мы просто используем @ символ, а затем тип обработчика событий, которые мы хотим сделать. Например, чтобы добавить прослушиватель события клика, мы можем написать следующее:
<div class=”ToDo-Add” @click=”createNewToDoItem()”>+</div>
Примечание: @click
на самом деле это сокращение для письма v-on:click
. Прекрасная вещь с прослушиванием событий Vue заключается в том, что есть также куча вещей, которые вы можете привязать к ним, например .once
, что предотвращает запуск прослушивателя событий несколько раз. Существует также куча ярлыков, когда дело доходит до написания конкретных обработчиков событий для обработки нажатий клавиш.
Я обнаружил, что создание прослушивателя событий в React для создания новых элементов ToDo каждый раз, когда нажималась кнопка ввода, заняло немного больше времени. В Vue я смог просто написать:
<input type=”text” v-on:keyup.enter=”createNewToDoItem”/>
Как мы передаем данные дочернему компоненту?
Отреагировать:
В React мы передаем props дочернему компоненту в месте его создания. Как вот:
<ToDoItem key={key} item={todo} />
Здесь мы видим две опоры, переданные в ToDoItem компонент. С этого момента мы можем ссылаться на них в дочернем компоненте через this.props
. Итак, чтобы получить доступ к item.todo
prop, мы просто называем this.props.item
.
Vue:
В Vue мы передаем props дочернему компоненту в месте его создания. Как вот:
<ToDoItem v-for="todo in list"
:todo="todo"
:key="todo.id"
@delete="onDeleteItem" />
Когда это будет сделано, мы передаем их в массив props в дочернем компоненте, как таковой: props: [ ‘todo’ ]
. Затем на них можно ссылаться в ребенке за их именем – поэтому в нашем случае, ‘todo’
.
Как мы передаем данные обратно к родительскому компоненту?
Отреагировать:
Сначала мы передаем функцию дочернему компоненту, ссылаясь на нее как на сопротивление в том месте, где мы вызываем дочерний компонент. Затем мы добавляем вызов функции к ребенку любым способом, например onClick
путем ссылки this.props.whateverTheFunctionIsCalled
. Тогда это запустит функцию, находящуюся в родительском компоненте.
Мы можем увидеть пример всего этого процесса в разделе «Как удалить из списка».
Vue:
В нашем дочернем компоненте мы просто пишем функцию, возвращающую значение родительской функции. В нашем родительском компоненте мы пишем функцию, которая прослушивает, когда выделяется это значение, которое затем может вызвать вызов функции. Мы можем увидеть пример всего этого процесса в разделе «Как удалить из списка».
И вот у нас! ?
Мы рассмотрели, как мы добавляем, удаляем и изменяем данные, передаем данные в форме реквизитов от родителей к дочернему и посылаем данные от ребенка к родительскому в виде прослушивателей событий.
Конечно, между React и Vue есть много других небольших отличий и прихотей, но, надеюсь, содержание этой статьи помог послужить основой для понимания того, как обе фреймворки обрабатывают вещи?
Если вы нашли это полезно, поделитесь им в социальных сетях и прокомментируйте!
Github ссылки на обе программы:
Vue ToDo: https://github.com/sunil-sandhu/vue-todo
React ToDo: https://github.com/sunil-sandhu/react-todo
Это синдицированный репост для freeCodeCamp в сотрудничестве с Javascript In Plain English. Оригинальную версию этой статьи можно найти здесь.