Backbone.js開発者が犯す最も一般的な8つの間違い

公開: 2022-03-11

Backbone.jsは、構造化されたWebアプリケーションのフロントエンドを作成するために使用できるデータ構造と機能の単純なセットを提供することを目的とした最小限のフレームワークです。 箱から出してすぐに、Backbone.jsのコンポーネントは、バックエンドでモデルやビューを操作するときにすでに慣れ親しんでいる直感的な環境を提供します。 Backbone.jsのモデルとコレクションは単純ですが、REST JSON APIと簡単に統合するオプションなど、いくつかの非常に便利な機能が付属しています。 しかし、それらはまた、ほとんどすべての実際の使用に適応するのに十分な柔軟性があります。

このBackbone.jsチュートリアルでは、フリーランスの開発者がBackbone.jsの学習に最初に挑戦することでよくある間違いと、それらを回避する方法について説明します。

間違い#1:Backbone.js機能のアーセナルを無視する

Backbone.jsは最小限のフレームワークかもしれませんが、(Underscore.jsとともに)最新のWebアプリケーションを開発するときに発生する最も基本的で重要なニーズのいくつかを簡単にカバーできる多数の機能を提供します。 初心者の開発者がよく犯すよくある間違いの1つは、Backbone.jsをWeb用のさらに別のMVCのようなクライアントフレームワークと見なすことです。 このセクションでは非常に明白なことについて説明していますが、Backbone.jsに関しては、フレームワークを完全に調査しないことは非常に重大な間違いです。 フレームワークのサイズは小さいかもしれませんが、これがこの徹底的な調査の優れた候補となっています。 特に、小さくて適切に注釈が付けられたソースコード。

Backbone.jsは、Webアプリケーションに恩恵を受けることができる構造を与えるために最低限必要なものを提供します。 その拡張性と多数のプラグインにより、Backbone.jsの学習を使用して、いくつかのすばらしいWebアプリケーションを構築できます。 Backbone.jsの最も明白な機能のいくつかは、モデル、コレクション、およびビューを通じて公開されています。 ルーターおよび履歴コンポーネントは、クライアント側のルーティングをサポートするためのシンプルでありながら洗練されたメカニズムを提供します。 Underscore.jsはBackbone.jsの依存関係ですが、モデルとコレクションの両方がJavaScript用のこの驚くべきユーティリティベルトから多くの恩恵を受けており、自由に利用できるため、フレームワークにかなりうまく統合されています。

フレームワークのソースコードは非常によく書かれており、注釈が付けられているため、コーヒーを飲みながらすべてを読むことができます。 初心者は、フレームワークが内部でどのように機能するかについて多くを学ぶことができ、JavaScriptに関しては、優れたベストプラクティスのセットを採用できるため、ソースアノテーションを読むことで多くのメリットを得ることができます。

間違い#2:任意のイベントに直接応答してDOMを変更する

Backbone.jsを最初に学び始めたときに私たちがしがちなことは、Backbone.jsが推奨するようなことをしないことです。 たとえば、単純なWebサイトでjQueryを使用する場合と同じように、イベントを処理して更新を表示する傾向があります。 Backbone.jsは、関心の分離を適切に行うことで、Webアプリケーションに堅固な構造を与えることを目的としています。 Backbone.jsでよく行うことは、任意のDOMイベントに応答してビューを更新することです。

 var AudioPlayerControls = Backbone.View.extend({ events: { 'click .btn-play, .btn-pause': function(event) { $(event.target).toggleClass('btn-play btn-pause') } }, // ... })

これは絶対に避けなければならないことです。 これが理にかなっているかもしれないあいまいな例を思い付くことが可能かもしれません。 しかし、ほとんどの場合、それを行うにははるかに優れた方法があります。 実際、ここで例示できる1つの方法は、モデルを使用してオーディオプレーヤーの状態を追跡し、その状態情報を使用してボタン(またはより具体的にはそのクラス名)をレンダリングすることです。

 var AudioPlayerControls = Backbone.View.extend({ events: { 'click .btn-play, .btn-pause': function(event) { this.model.set('playing', !this.model.get('playing')) } }, initialize: function() { this.listenTo(this.model, 'change', this.render) this.render() }, // ... })
 <button class=”btn btn-<%- playing ? 'pause' : 'play' %>”></button>

イベントハンドラーからのDOMの直接操作が理にかなっているというまれな状況があるかもしれませんが、イベントハンドラーからの複雑なDOM操作の管理に伴うコストはほとんど価値がありません。 これはBackbone.jsが解決しようとしていることです。 Backbone.jsを使用してこのようなことを行うのは間違いです。

間違い#3:レンダリングのコストを過小評価する

Backbone.jsを使用すると、DOMを自由に、またはイベントに応じて非常に簡単にレンダリングおよび再レンダリングできるため、これがWebアプリケーションの全体的なパフォーマンスにどの程度の影響を与えるかを見落としがちです。 ビューでrenderメソッドをスラッシングする方法はたくさんあります。 最近のWebブラウザーはパフォーマンスの高いソフトウェアになりつつあるため、これはそれほど多くないように思われることがよくあります。 しかし、Webアプリケーションが成長し、処理するデータの量が増えるにつれて、パフォーマンスの低下がますます明らかになります。

モデルの小さなコレクションから始めて、それをリストビューにレンダリングするという不自然な例を通して、これが実際に動作していることを確認できます。

 var AudioPlayerPlaylist = Backbone.View.extend({ template: _.template('<ul> <% _.each(musics, function(m) { %> <li><%- m.title %></li> <% }) %> </ul>'), initialize: function() { this.listenTo(this.collection, 'add', this.render) }, // ... })

このBackbone.jsの例では、モデルがコレクションに追加されるたびに再レンダリングしています。 これは正常に機能します。 ただし、モデルがリストに追加されるたびに「追加」イベントが発生するため、サーバーからモデルの大規模なリストをフェッチすることを想像してください。 renderメソッドは、サーバーからの応答のモデルごとに1回ずつ、連続して複数回呼び出されます。 十分に大きなモデルは、アプリケーションを混乱させ、ユーザーエクスペリエンスを台無しにするのに十分です。 レンダリングされるビューの複雑さによっては、小さな応答で十分な場合もあります。

これに対する非常に迅速な解決策は、追加されるすべてのモデルに対してrenderメソッドを呼び出さないことです。 このような状況では、モデルはバッチで追加され、実際には、renderメソッドが呼び出されたときにのみ起動し、指定された時間内に再起動されないようにすることができます。 Backbone.jsの依存関係Underscore.jsには、このための便利なユーティリティ関数「_.debounce」が付属しています。 これを利用するために必要なのは、イベントバインディングJavaScriptの行を次のように変更することだけです。

 this.listenTo(this.collection, 'add', _.debounce(_.bind(this.render), 128))

これにより、「追加」イベントが発生するたびにイベントコールバックが発生しますが、実際にrenderメソッドを呼び出す前に、最後のイベントから128ミリ秒待機します。

ほとんどの場合、これは解決策のようなクイックフィックスと見なされます。 実際、レンダリングのスラッシングを回避するためのより適切な方法があります。 Trelloの背後にいる開発者は、Backbone.jsを使用しながらレンダリングパフォーマンスを向上させるための経験とアプローチについて説明するブログ投稿を書いたことがあります。

間違い#4:イベントリスナーをその使用を超えて拘束したままにする

未使用のイベントリスナーをバインドしたままにしておくことは、使用しているJavaScriptフレームワークに関係なく、または使用しているJavaScriptフレームワークに関係なく発生する可能性があります。 Backbone.jsを使用するとこの問題を簡単に回避できますが、Webアプリケーションでメモリリークが発生しやすいように潜在的な穴を残すのは間違いです。 Backbone.jsの「イベント」コンポーネントは確かにかなりきちんとした実装です。 これにより、JavaScriptオブジェクトはイベントベースの機能を簡単に実装できます。 ビューは、イベントの消費のほとんどが通常発生する場所であるため、そこでこの間違いを犯しやすいです。

 var AudioPlayerControl = Backbone.View.extend({ initialize: function() { this.model.on('change', _.bind(this.render, this)) // ... }, // ... })

このコードスニペットのイベントバインディング行は、最初の例の行とそれほど変わりません。 ここで行ったのは、「this.listenTo(this.model、…)」を「this.model.on(…)」に変更したことだけです。 他のJavaScriptフレームワークやライブラリでの経験から、イベントバインディングの「.on()」呼び出しに非常に慣れているため、Backbone.jsを使い始めると、バインドに「.on()」呼び出しを使用する傾向があります。イベント。 これは、イベントハンドラーが不要になったときに、「。off()」を呼び出してバインドを解除する必要がない場合にのみ、問題ありませんでした。 しかし、それを行うことはめったになく、最終的にはメモリリークの原因になります。

Backbone.jsは、この問題を解決する簡単な方法を提供します。 これは、「object.listenTo()」メソッドを使用することによって行われます。 これにより、「listenTo()」を呼び出しているオブジェクトが、リッスンしているイベントを追跡できるようになります。また、これらのすべてのイベントを一度に簡単にバインド解除できます。 たとえば、ビューで「remove()」を呼び出すとすぐに、バインドされたすべてのイベントのリッスンが自動的に停止します。

間違い#5:モノリシックビューの作成

あなたがそれについて考えるならば、Backbone.jsのミニマリズムはあなたがあなたのウェブアプリケーションのフロントエンドをどのように設計したいかに途方もない量の柔軟性を提供します。 モデル、コレクション、およびビューがコンポーネントの構成要素であるため、それらを可能な限り軽量かつ具体的に保つことが不可欠です。 多くの場合、コードの観点からWebアプリケーションの最も重い側面になるのはビューです。 しかし、アプリケーションが提供するすべてのことを実行しようとする巨大なモノリシックビューを作成しないことが非常に重要です。 すべてのロジックが詰め込まれた巨大な「AudioPlayer」ビューを作成する代わりに、プレイリストのビュー、コントロールのビュー、ビジュアライザーのビューなど、いくつかの論理ビューに分割します。 どのような粒度を確保したいかは、おそらく構築しようとしているアプリケーションによって異なります。

これは、各ビューが特定のことを正しく実行する詳細なビューでは、Backbone.jsを使用してWebアプリケーションを開発するのが簡単になるためです。 コードは、より保守しやすく、将来的に拡張または変更しやすいものにする必要があります。 それから、あなたがそれをやり過ぎてしまうもう一つの極端があります。 Backbone.jsビューは、モデルまたはコレクションを操作するのに便利になるように設計されており、これはおそらく、アプリケーションをどのように構造化するかについてのヒントとして機能する可能性があります。 Ian Storm Taylorは、彼のブログで、ビューを実装する際におそらく覚えておくべきいくつかの貴重なアイデアを共有しました。

間違い#6:Backbone.jsが非RESTfulAPIに適応できることに気付いていない

Backbone.jsは、JSONベースのRESTfulAPIですぐに使用できます。 そのために必要なのはjQuery(またはZeptoなどのドロップイン代替品)だけです。 ただし、Backbone.jsは非常に拡張可能です。 実際、Backbone.jsは、他のタイプのAPIや他のタイプのエンコード形式を使用するように適合させることができます。

フロントエンドとバックエンドサービスの相互作用を処理するBackbone.jsのコンポーネントは、「同期」です。 このコンポーネントは、Backbone.jsのAPIエンドポイントとの対話方法をカスタマイズするために簡単にオーバーライドできるいくつかの属性を公開します。 実際、デフォルトの同期メカニズムを、バックエンドサービスの代わりに、localStorageを使用してデータを永続化するなど、控えめに言ってもそれほど伝統的ではないものに置き換えることもできます。

Backbone.jsの同期動作を簡単にカスタマイズできるプラグインが多数存在します。 たとえば、Backbone.dualStorageというプラグインを使用すると、バックエンドサービスとlocalStorageの両方を使用してデータを永続化できます。 アプリケーションがオフラインになると、プラグインはlocalStorageを使用して、キャッシュされたデータからのリクエストを処理し続け、後でオンラインになったときにサーバーと同期する可能性のある変更を追跡します。

RESTfulで互換性があるように設計されたバックエンドでBackbone.jsを使用する方が使いやすいですが、Backbone.jsがすべて機能するわけではありません。 デフォルトのBackbone.js同期メカニズムにいくつかの変更を加えることで、さまざまなバックエンドサービスAPIとエンコード形式に適応させることができます。

Backbone.jsの他の部分も柔軟性があり、オプションであることに言及する価値があります。 たとえば、Underscore.jsに付属しているデフォルトのテンプレートエンジンを使用する必要はありません。 Backbone.jsのビューコンポーネントを使用する必要はなく、必要に応じて完全に別のものに置き換えることができます。

間違い#7:モデルではなくビューにデータを保存する

Backbone.jsを学ぶ初心者としてよくある間違いのひとつは、データを属性としてビューに直接保存することです。 このデータは、一部の状態または一部のユーザー選択を追跡するために存在する場合があります。 これは避けるべきものです。

 var AudioPlayerVisualizer = Backbone.View.extend({ events: { 'click .btn-color': function(event) { this.colorHex = $(event.target).data('color-hex') this.render() } }, // ... })

エンドポイントなしで、いつでも追加のモデルとコレクションを作成できます。 これらは、必ずしもバックエンドで永続化する必要がないデータ、または本質的に一時的なデータを保存するのに役立ちます。 それらをモデルに保存すると、変更をリッスンできるという利点があります。 関連するビュー、または複数のビューでさえ、これらのモデルを観察し、必要に応じて自分自身を再レンダリングできます。

実際に状態追跡変数をビューに保存し、それらを変更するたびにrenderメソッドを呼び出さなければならなかったと想像してみてください。 このrenderメソッドへの呼び出しが1つだけ欠落していると、ユーザーが画面上で経験していることに関して、アプリケーションが壊れた状態のままになる可能性があります。 さらに、小さなビューでは、これらの状態変数を複数のビューオブジェクトで同期してから、それらのオブジェクトでrenderメソッドを呼び出す必要がある場合があります。

間違い#8:委任されたイベントの代わりにjQuery「.on()」を使用する

私の意見では、Backbone.jsにはDOMイベントを処理する素晴らしい方法が1つあります。 それを使用しないと、多くの欠点が生じます。 jQueryの「.on()」イベントバインディング関数は便利に感じるかもしれませんが、長い目で見れば面倒であることがよくあります。 たとえば、要素がDOMから切り離されると、jQueryは「.on()」を使用して要素にバインドされたすべてのイベントハンドラーを自動的に削除します。 つまり、ビュー内からバインドしようとするDOMイベントは、ルート要素をDOMから切り離して再接続した場合に、再バインドする必要があります。

 var AudioPlayerControls = Backbone.View.extend({ events: { 'click .btn-play, .btn-pause': function() { /* ... */ }, 'click .btn-prev': function() { /* ... */ }, 'click .btn-next': function() { /* ... */ }, 'click .btn-shuffle': function() { /* ... */ }, 'click .btn-repeat': function() { /* ... */ } }, // ... })

このビューに対応する要素がDOMに再接続されると、ビューで「delegateEvents()」を呼び出してこれらすべてのイベントをバインドするだけです。

これらのイベントがどのようにバインドされるかを理解することが重要であることに注意してください。 Backbone.jsは、セレクターで指定された要素にイベントをバインドする代わりに、実際にはイベントハンドラーをビューのルート要素にバインドします。 これはほとんどすべての場合に正常に機能し、実際、ほとんどのニーズに適しています。 ビューのDOMサブツリーの子要素を変更または置換するために、Backbone.jsが新しい要素で各イベントを再度バインドする必要はありません。 既存のリスナーは機能し続けます。

ただし、これにより、特定のイベントをリッスンできなくなります。 1つの例は、「ウィンドウ」または子のスクロール可能な要素でスクロールイベントをリッスンしたい場合です。 子要素の場合、その要素のサブビューを作成し、そこでイベントを処理できます。

結論

非常にコンパクトでありながら拡張可能なフレームワークであるBackbone.jsは、舞台裏で大きな柔軟性を必要とするWebアプリケーションに最適です。 Angular.jsやEmber.jsなど、やりたいことを実行する方法を常に教えてくれるフレームワークとは異なり、Backbone.jsは一歩後退し、強力なツールセットを提供し、使用方法を決定できます。彼ら。 初心者向けのこのBackbone.jsチュートリアルが、一般的な開発ミスのいくつかを回避し、それを使って素晴らしいものを構築するのに役立つことを願っています。