JSX:アンチパターンかどうか?

かなり頻繁に、Reactと特にJSXテンプレートが悪いと聞きますが、良い開発者はそうではありません。 ただし、レイアウトとテンプレートを1つのファイルに混在させることが有害である理由については、多くの場合説明されいません。 そして、これで今日それを解明しようとします。







「各テクノロジーには独自のファイルがあります」というアプローチはWebの初めから使用されているため、このテンプレートを廃棄すると一部の開発者が拒否することは驚くことではありません。 しかし、「いいえ、私たちはそれを決してしません」と宣言する前に、ストーリーを理解し、JSXを使用できる理由を理解することが役立ちますが、スクリプトとhtmlを混ぜてください-いいえ。









物語



当初から、Webは静的なHTMLページのみで構成されていました。 アドレスを開くと、サーバーはページのコンテンツを返しました。 レイアウト、スタイル、スクリプト-すべてが共通のヒープにありました。







ただし、サイトがより複雑になると、異なるページでスタイルとスクリプトを再利用する必要が生じました。 やがて、HTMLアプローチとは別のCSSとJSが一般的な推奨事項になりました。 特にHTMLは、開発中にのみ変更され、サーバーによってそのまま提供されるCSSおよびJSファイルとは異なり、サーバーエンジンによって生成されます。 コンテンツを静的と動的に分離することで、ユーザーはキャッシュによりダウンロードするデータを減らすことができ、CMSが使用するテンプレートでJavascriptの部分を探すよりも、開発者が静的ファイルを編集する方が便利です。







時間が経つにつれて、ロジックの大部分がクライアント側に焦点を合わせた1ページのWebアプリケーションがますます登場し始めました。 サーバーは同じ静的HTMLを任意のURLに送信し、ユーザーのブラウザーのJavascriptコードが現在のアドレスを判別し、必要なデータをサーバーに要求します。 リンクをクリックすると、ページは完全にはリロードされませんが、URLは更新されるだけで、Javascriptコードは次のページの新しいリクエストを作成します。







Webアプリケーションの出現により、開発へのアプローチが根本的に変わりました。 多くのコードと複雑なユーザーインターフェイスロジックを持つWebアプリケーションを作成するために設計された新しい特別なフレームワークがあります。 データはクライアント上でレンダリングされ、ページhtmlテンプレートはページリソースに保存され、サーバーから受信したデータによってプルされます。







このような大量のコードを整理する最も適切な方法は、コンポーネントアプローチです。 多かれ少なかれ独立した各ブロックは、独自のスタイル、テンプレート、Javascriptを備えた個別のコンポーネントになり、ページ全体がこれらのブロックから組み立てられます。







このアプローチはほとんどの最新のJSフレームワークで実装されていますが、Angular、Ember、Marionetteが異なるテンプレートファイルの作成を推奨し、ReactがJS内にHTMLを記述することを推奨しています。 そして、これは一部の開発者にとっては赤い布になりつつあります。







テンプレートとコンポーネント



また、テンプレートを使用して別のファイルを作成する意味は何ですか? 引数はしばしば与えられます:異なるエンティティを分離することそれはとても正しいからです。 歴史的にHTMLとJSを分離する理由は静的と動的の分離でしたが、これはクライアントでのレンダリングにはもはや関係ありません







それでは、コンポーネントとそのテンプレートはどれくらい違いますか? コードを受け取ります









行は、あるファイルの変更が別のファイルに影響を与える関係を示しています。 これが2つのJSモジュール間のリンクである場合、リファクタリングは一目瞭然です。 しかし、ビューとテンプレートについては、 間違っています。







しばらく前、他の条件では、HTMLとJSを混合することは望ましくなく、現在まで、開発者は盲目的にそのルールに従っています。 しかし、クライアントでレンダリングする場合、状況は同じではありません。さらに、最初はHTMLからJSを削除することをお勧めしましたが、JSからHTMLを削除することはお勧めしませんでした。







そして、実際のプロジェクトではどれくらいの害がありますか? 実験を試して、テンプレートとJSを組み合わせてみましょう。







import Marionette from 'backbone.marionette';
import {warningText} from '../constants';

export default Marionette.ItemView.extend({
  template(templateData) {
    const {title, img_url, count} = templateData;
    const isSelected = this.model.isSelected();
    const isOverLimit = this.model.get('count') > this.model.get('maxAvailable')
    return `<div class="cart-item ${isSelected ? 'active' : ''}">
      <h3>${title}</h3>
      <img src="http://${img_url}" />
      <div>
        <button class="btn-less">-</button>
        <input value="${count}" />
        <button class="btn-more" ${isOverLimit ? 'disabled': ''}>+</button>
      </div>
      ${isOverLimit ? warningText : ''}
    </div>`;
  },
  events: {
    'click btn-less': 'onLessClick',
    'click btn-more': 'onMoreClick'
  }
});
      
      





EcmaScript6 template strings, . HTML . , , .







React? , , . , , HTML .








All Articles