Простое сравнение

Позвольте мне начать с того, что я не эксперт по Метеорам. Я постоянно учусь больше каждый день. Цель этой статьи — провести простое сравнение React и Blaze в контексте фреймворка Meteor. Я сделаю это, создав несколько сопоставимых компонентов, которые достигают тех же результатов. Что касается React, я предполагаю, что работаю в Meteor 1.3. Итак, начнем.

Вот шаблон Blaze:

<!-- contents of sample-template.html -->
<template name="sampleTemplate">
  <div class="hello-world">
    Hello {{world}}
  </div>
</template>

В приведенном выше примере я включил одного помощника. Итак, давайте определим его в нашем JS-файле.

//contents of sample-template.js
Template.sampleTemplate.helpers({
  world() {
    return 'World!';
  }
});

Очевидно, что вышесказанное настолько просто, насколько это возможно. Итак, давайте посмотрим, как это выглядит в React.

//contents of hello-world.jsx
import React from 'react';
const HelloWorld = ({world}) => (
  <div className="hello-world">
    Hello {world}
  </div>
);

Приведенный выше компонент HelloWorld React на самом деле известен как функция без сохранения состояния. Функция без сохранения состояния может принимать свойства; но, как следует из названия, компонент не обрабатывает состояние. Когда это возможно, это на самом деле предпочтительный метод React для разработки компонентов.

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

Прежде чем мы двинемся дальше, также обратите внимание, что class теперь className. Хотя иногда JSX может выглядеть как HTML, на самом деле это JavaScript. Поэтому имеет смысл, что вы не можете использовать атрибуты HTML, такие как class и for, и вместо этого должны использовать className и htmlFor.

Так как же определяется {world} в нашем примере выше. Ну, это происходит, когда мы на самом деле хотим отрендерить его. Наш компонент HelloWorld имеет одно свойство — мир. Поэтому мы просто определяем это свойство, как показано ниже.

<HelloWorld world="World!" />

Итак, как мы на самом деле визуализируем шаблон и компонент соответственно. Предположим, что мы используем Flow Router. Для Blaze мы используем BlazeLayout. Итак, в Blaze давайте визуализируем наш шаблон. Сначала создайте макет.

<!-- contents of layout.html -->
<template name="layout">
  <div>
    {{> Template.dynamic template=main}}
  </div>
</template>

Затем в маршрутизаторе давайте на самом деле визуализируем наш шаблон.

//contents of router.js
FlowRouter.route('/', {
  name: 'home',
  action() {
    BlazeLayout.render('layout', {
      main: 'sampleTemplate'
    });
  }
});

Теперь давайте сделаем то же самое в React. Вместо использования BlazeLayout мы будем использовать реактивный монтаж пакета NPM. Создадим макет.

//contents of layout.jsx
import React from 'react';
export const Layout = ({content}) => (
  <div>
    {content}
  </div>
);

Обратите внимание, что это еще одна функция без сохранения состояния, действующая как наш макет. Теперь давайте визуализируем наш компонент.

//contents of router.jsx
import React from 'react';
import {mount} from 'react-mounter';
import {Layout} from './layout.jsx';
import {HelloWorld} from './hello-world.jsx';
FlowRouter.route("/", {
  action() {
    mount(Layout, {
      content: (<HelloWorld world="World!" />),
    });
  }
});

Вот и все. В приведенных выше примерах Blaze и React очень похожи. Итак, давайте углубимся и создадим в React компонент с состоянием. Начнем снова с Блейза. Мы создадим простую форму, а затем покажем пользователю предупреждение с его вводом при отправке формы.

<!-- contents of sample-form.html -->
<template name="sampleForm">
  <form>
    <input type="text" name="userInput" />
    <button type="submit">Submit</button>
  </form>
</template>

Теперь давайте обработаем действие отправки этой формы.

//contents of sample-form.js
Template.sampleForm.events({
  'submit form': function(event,template) {
    event.preventDefault();
    const userEntered = template.$('[name=userInput]').val();
    alert('You entered: '+ userEntered);
  }
});

Давайте сделаем то же самое в React.

//contents of sample-form.jsx
import React from 'react';
class SampleForm extends React.Component {
  handleSubmit(event) {
    event.preventDefault();
    const userEntered = this.refs.userInput.value;
    alert('You entered: '+ userEntered);
  }
  render() {
    return (
      <form onSubmit={this.handleSubmit.bind(this)}>
        <input ref="userInput" type="text" />
        <button type="submit">Submit</button>
      </form>
    );
  }
}
export default SampleForm;

Вот и все. Теперь давайте представим, что мы хотим отобразить эти вещи прямо под нашим предыдущим шаблоном/компонентами. Давайте сначала сделаем Blaze.

<!-- contents of sample-template.html -->
<template name="sampleTemplate">
  <div class="hello-world">
    Hello {{world}}
  </div>
  {{> sampleForm}}
</template>

И в Реакт.

//contents of hello-world.jsx
import React from 'react';
import SampleForm from './sample-form.jsx';
export const HelloWorld = ({world}) => (
  <div>
    <div className="hello-world">
      Hello {world}
    </div>
    <SampleForm />
  </div>
);

Вот и все. Вот — пример репо, который мы сделали с помощью Meteor 1.3 и React. Таким образом, цель этого сравнения — просто указать на некоторое сходство с использованием Blaze и React в контексте Meteor. Я не предлагаю использовать один над другим (хотя и понятно, что сообщество Meteor движется в сторону React). Моей целью было представить что-то очень простое. Таким образом, несмотря на то, что эти шаблоны являются базовыми, их можно расширить. Для Blaze источник — guide.meteor.com. У React есть ряд ресурсов; но в контексте Meteor я бы настоятельно рекомендовал серию видео Саши при переключении приложения Blaze на приложение React. Надеюсь, это было полезно для тех, кто пытался переключиться с Blaze на React.

Обновление: в Foodful мы используем как React, так и Blaze для создания нашего приложения. Загляните к нам на http://foodfully.com/