Ractive.js-Webアプリを簡単に

公開: 2022-03-11

今日の急速に急増しているJavaScriptフレームワークとライブラリの状況では、開発のベースにするものを選択することは非常に困難な場合があります。 結局のところ、特定のフレームワークを使用する道をたどると、コードを別のフレームワークを使用するように移行することは簡単な作業ではなく、実行する時間や予算がない可能性があります。

では、なぜRactive.jsなのか?

不活性なHTMLを生成する他のツールとは異なり、Ractiveはテンプレートをデフォルトでインタラクティブなアプリのブループリントに変換します。 そして、Ractiveの貢献は革命的というよりも進化的であると確かに主張することができますが、それでもその価値は重要です。

Ractiveを非常に便利なものにしているのは、強力な機能を提供することですが、開発者が使用するのに非常に簡単な方法でそれを行います。 さらに、それはかなりエレガントで、速く、邪魔にならず、そして小さいです。

この記事では、単純なRactive検索アプリを構築するプロセスについて説明し、Ractiveの主要な機能のいくつかと、それがWebアプリと開発を簡素化するのに役立つ方法を示します。

Ractive.jsとWebアプリ

Ractive.jsとは何ですか?

Ractiveは元々、よりエレガントな方法でデータバインディングの問題に取り組むために作成されました。 そのために、テンプレートを取得してDOMの軽量仮想表現に変換し、データが変更されたときに実際のDOMがインテリジェントかつ効率的に更新されるようにします。

しかし、Ractiveが採用しているアプローチとインフラストラクチャを使用して、他のことをより効率的に行うことができることがすぐに明らかになりました。 たとえば、イベントハンドラーの再利用などを自動的に処理し、不要になったときに自動的にバインドを解除できます。 イベントの委任は不要になります。 データバインディングと同様に、このアプローチは、アプリの成長に伴ってコードが扱いにくくなるのを防ぎます。

双方向バインディング、アニメーション、SVGサポートなどの主要な機能がすぐに提供され、プラグインを介してカスタム機能を簡単に追加できます。

一部のツールとフレームワークでは、新しい語彙を学習し、特定の方法でアプリを構造化する必要がありますが、Ractiveはその逆ではなく、機能します。 また、他のライブラリともうまく統合できます。

私たちのサンプルアプリ

サンプルアプリは、スキルに基づいて開発者のToptalデータベースを検索するために使用されます。 私たちのアプリには2つのビューがあります:

  • 検索:インライン検索ボックス付きのスキルリスト
  • 結果:開発者のリストを含むスキルビュー

開発者ごとに、名前、写真、簡単な説明、スキルのリストを表示します(各スキルは対応するスキルビューにリンクします)。

(注:アプリケーションのオンライン作業インスタンスとソースコードリポジトリへのリンクは、どちらもこの記事の最後にあります。)

Ractiveフレームワークへの主な焦点を維持するために、通常は本番環境では実行されるべきではないいくつかの簡略化を採用します。

  • デフォルトのテーマ。 アプリのスタイルに合わせてテーマをカスタマイズするのではなく、デフォルトのテーマでBootstrapを使用してスタイリングします。
  • 依存関係。 依存関係を、グローバル変数を定義する個別のスクリプトとして追加します(ES6モジュール、CommonJS、または開発用の適切なローダーを備えたAMD、および本番用のビルドステップを使用するのではありません)。
  • 静的データ。 Toptalサイトの公開ページをスクレイピングして作成した静的データを使用します。
  • クライアント側のルーティングはありません。 これは、ビューを切り替えてもURLが同じままであることを意味します。 一部の小さなインタラクティブコンポーネントでは問題ないかもしれませんが、SPAでは絶対にそうすべきではありません。 Ractiveにはルーターの実装が組み込まれていませんが、この例に示すように、サードパーティのルーターで使用できます。
  • HTMLのスクリプトタグ内で定義されたテンプレート。 これは、特に小さなアプリケーションでは必ずしも悪い考えではなく、いくつかの利点があります(単純であり、たとえば国際化のために、これらのクライアント側のテンプレートをサーバー側のテンプレートと一緒に処理できます)。 ただし、より大きなアプリの場合は、事前コンパイル(つまり、テンプレートを内部JS表現に事前解析する)の恩恵を受けることができます。

Webアプリを始めましょう

それでは、アプリの作成を始めましょう。 これを繰り返し実行し、小さな機能を1つずつ追加して、それらに遭遇したときに概念を調査します。

まず、 index.htmlscript.jsの2つのファイルを含むフォルダーを作成しましょう。 私たちのアプリは非常にシンプルで、開発サーバーを起動する必要をなくすためにfile://プロトコルから動作します(必要に応じて起動できます)。

検索ページ

まず、ユーザーがToptalデータベースで一致する開発者を見つけるスキルを選択できる検索ページを実装することから始めます。

HTMLスケルトン

この些細なHTMLページから始めましょう:

 <html> <head> <title>Toptal Search</title> <!-- LOAD BOOTSTRAP FROM THE CDN --> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css"> </head> <body> <!-- SOME BASIC STATIC CONTENT --> <div class="container"> <h1>Toptal Search</h1> </div> <!-- LOAD THE JAVASCRIPT LIBRARIES WE NEED --> <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/3.9.3/lodash.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/ractive/0.7.3/ractive.min.js"></script> <!-- LOAD THE DATA --> <script src="https://rawgit.com/emirotin/toptal-blog-ractive/master/data.js"></script> <!-- LOAD OUR SCRIPT --> <script src="script.js"></script> </body> </html>

ご覧のとおり、これは簡単なHTML5ドキュメントです。 CDN、Lodash(素晴らしいデータ操作ライブラリ)、およびRactive.jsからBootstrapをロードします。

Ractiveは、ページ全体をSPAに割り当てる必要がないため、静的なコンテンツを含めることができます。 この場合、これはコンテナ要素とページタイトルで構成されます。

最後に、デモ用に準備したデータと、プログラムを含むスクリプトをロードします。

では、HTMLスケルトンが配置されたので、実際の機能の追加を始めましょう。

スキルのリスト

Ractiveについて私が特に気に入っていることの1つは、達成したい最終的な表現(HTML)について考える方法を教えてくれることです。そして、それを実現するために必要なコードの記述に集中できます。

まず、最初のビューとしてスキルのリストを作成しましょう。 これを行うには、次のことが必要です。

  • スキルリストが表示されるHTML要素を追加します。
  • テンプレートコードの小さなスニペットをHTMLに追加します。
  • 追加したHTML要素でデータをレンダリングするために、テンプレートにデータを提供する簡単でシンプルなJavaScriptを作成します。

HTMLのmodは、次のもので構成されています。

 <div class="container"> <h1>Toptal Search</h1> <div></div> <!-- THIS IS THE NEW HTML ELEMENT --> </div> <!-- THIS IS THE SMALL SNIPPET OF TEMPLATE CODE --> <script type="text/html"> <div class="row"> {{#each skills}} <span class="col-xs-3"> <a href="#" class="label label-primary">{{this}}</a> </span> {{/each}} </div> </script>

表示するデータを受け取るHTML要素を指定するためのRactiveの特別な規則はありませんが、それを行う最も簡単な方法は、要素にIDを追加することです。 私は通常、この目的のために「ルート」IDを使用します。 Ractiveが初期化されるときにどのように使用されるかはすぐにわかります。 好奇心旺盛な人のために、ルート要素を指定する他の方法があります。

type="text/html"の少し厄介なスクリプト要素は、ブラウザが不明なタイプのスクリプトを無視するため、HTMLのチャンクを解析またはレンダリングせずにブラウザにロードするための巧妙なトリックです。 スクリプトの内容は、Mustache / Handlebarsのようなテンプレートです(ただし、Ractiveにはいくつかの拡張機能があります)。

まず、スキル配列にアクセスできることを前提として、テンプレートコードを記述します。 {{#each}}口ひげディレクティブを使用して反復を定義します。 ディレクティブ内では、現在の要素にthisとしてアクセスできます。 繰り返しになりますが、skills変数は文字列の配列を保持していると想定しているため、補間口ひげ{{this}}を使用してレンダリングするだけです。

OK、それはHTMLです。 しかし、JavaScriptはどうですか? ここで、データをテンプレートに提供する「魔法」が発生します。

 (function () { var skills = DB.skills, developers = DB.developers; var app = new Ractive({ el: '#root', template: '#tpl-app', data: { skills: _.keys(DB.skills) } }); }());

印象的ですねその10行のコードで、次のことが可能になります。

  1. 「DB」からデータを「取得」します。
  2. 新しいRactiveアプリをインスタンス化します。
  3. 要素の内部をレンダリングするように指示します
  4. スクリプト要素を使用するように指示しますテンプレートを取得する(他の方法もあります)。
  5. 初期データ(実行時に変更する方法を説明します)を渡すか、Angularの用語に慣れている場合は「スコープ」を渡します。
  6. lodash keysメソッドを使用して、「DB」でオブジェクトキーとして使用するスキル名を取得します。

したがって、基本的にこのスクリプトを使用して、フレームワークに何をすべきかを指示しますが、どのように実行するかは指示しません。 テンプレートは、私が個人的に非常に素晴らしく自然だと思う方法を宣言しています。

うまくいけば、あなたはアイデアを理解し始めているので、今、私たちが持っているものの上にもっと便利なものを実装しましょう。

スキル検索

もちろん、検索ページには検索フィールドが必要です。 また、ユーザーが検索ボックスに入力すると、スキルのリストに入力された部分文字列を含むスキルのリストのみが含まれるインタラクティブな機能を提供する必要があります(フィルタリングでは大文字と小文字が区別されません)。

Ractiveでいつものように、テンプレートを定義することから始めます(どの新しいコンテキスト変数が必要になるか、そしてデータ管理に関して何が変わるかを考えながら):

 <div class="container"> <h1>Toptal Search</h1> <div></div> </div> <!-- THIS IS THE SMALL SNIPPET OF TEMPLATE CODE --> <script type="text/html"> <!-- HERE'S OUR SEARCH BOX --> <div class="row"> <form class="form-horizontal col-xs-6 col-xs-offset-6"> <input type="search" class="form-control" value="{{ skillFilter }}" placeholder="Type part of the skill name here"> </form> </div> <hr> <!-- NOW INSTEAD OF DISPLAYING ALL SKILLS, WE INVOKE A TO-BE-CREATED JAVASCRIPT skills() FUNCTION THAT WILL FILTER THE SKILL LIST DOWN TO THOSE THAT MATCH THE TEXT ENTERED BY THE USER --> <div class="row"> {{#each skills()}} <span class="col-xs-3"> <a href="#" class="label label-primary">{{this}}</a> </span> {{/each}} </div> </script>

それほど多くの変更はありませんが、それでもかなりの量を学ぶ必要があります。

まず、検索ボックスを含む新しい<div>を追加しました。 その入力をいくつかの変数に接続したいのは明らかです(古き良きjQueryスープの時代を懐かしんでいない限り)。 Ractiveは、いわゆる双方向バインディングをサポートしています。つまり、JSコードは、DOMから手動で値を読み取る必要なしに値を取得できます。 私たちの場合、これは補間口ひげvalue="{{ skillFilter }}"を使用して実現されます。 Ractiveは、この変数を入力のvalue属性にバインドすることを理解しています。 そのため、入力を監視し、変数を自動的に更新します。 たった1行のHTMLでかなりきれいです。

次に、上記のコードスニペットのコメントで説明されているように、すべてのスキルを表示する代わりに、スキルリストをフィルタリングしてユーザーが入力したテキストに一致するスキルのみを返すskills() JS関数を作成します。

 // store skill list in a variable outside of Ractive scope var skillNames = _.keys(DB.skills); var app = new Ractive({ el: '#root', template: '#tpl-app', data: { // initializing the context variable is not strictly // required, but it is generally considered good practice skillFilter: null, // Define the skills() function right in our data object. // Function is available to our template where we call it. skills: function() { // Get the skillFilter variable from the Ractive instance // (available as 'this'). // NOTE WELL: Our use of a getter here tells Ractive that // our function has a *dependency* on the skillFilter // value, so this is significant. var skillFilter = this.get('skillFilter'); if (!skillFilter) { return skillNames; } skillFilter = new RegExp(_.escapeRegExp(skillFilter), 'i') return _.filter(skillNames, function(skill) { return skill.match(skillFilter); }); } } });

これはクリーンで実装が簡単ですが、パフォーマンスにどのように影響するか疑問に思われるかもしれません。 つまり、毎回関数を呼び出すのですか? さて、毎回何? Ractiveは、依存関係(変数)が変更されたときにテンプレートの一部のみを再レンダリングする(そしてそれらから関数を呼び出す)のに十分賢いです(Ractiveは、セッターの使用のおかげでそれがいつ発生するかを知っています)。

ちなみに、これをさらに一歩進めたい人のために、計算されたプロパティを使用してこれを行うよりエレガントな方法もありますが、必要に応じて、それを自分で試してみてください。

結果ページ

非常に使いやすい検索可能なスキルリストができたので、結果ビューに移動して、一致する開発者のリストを表示します。

スキルビューへの切り替えとスキルビューからの切り替え

これを実装する方法は明らかに複数あります。 スキルが選択されているかどうかに応じて、2つの異なるビューがあるというアプローチを選択しました。 その場合、一致する開発者のリストを表示します。 そうでない場合は、スキルリストと検索ボックスが表示されます。

したがって、初心者の場合、ユーザーがスキル名を選択(つまりクリック)すると、スキルリストを非表示にする必要があり、代わりにスキル名をページ見出しとして表示する必要があります。 逆に、選択したスキルビューでは、そのビューを閉じてスキルのリストに戻る方法が必要です。

このパスをたどる最初のステップは次のとおりです。

 <script type="text/html"> <!-- PARTIAL IS A NEW CONCEPT HERE --> {{#partial skillsList}} <div class="row"> <form class="form-horizontal col-xs-6 col-xs-offset-6"> <input type="search" class="form-control" value="{{ skillFilter }}" placeholder="Type part of the skill name here"> </form> </div> <hr> <div class="row"> {{#each skills()}} <span class="col-xs-3"> <!-- MAKE OUR SKILLS CLICKABLE, USING PROXY EVENTS --> <a href="#" class="label label-primary" on-click="select-skill:{{this}}">{{this}}</a> </span> {{/each}} </div> {{/partial}} {{#partial skillView}} <h2> <!-- DISPLAY SELECTED SKILL AS HEADING ON THE PAGE --> {{ currentSkill }} <!-- CLOSE BUTTON TAKES USER BACK TO SKILLS LIST --> <button type="button" class="close pull-right" on-click="deselect-skill">&times; CLOSE</button> </h2> {{/partial}} <!-- PARTIALS ARE NOT IN THE VIEW UNTIL WE EXPLICITLY INCLUDE THEM, SO INCLUDE THE PARTIAL RELEVANT TO THE CURRENT VIEW. --> {{#if currentSkill}} {{> skillView}} {{else}} {{> skillsList}} {{/if}} </script>

OK、ここでたくさんのことが起こっています。

まず、これを2つの異なるビューとして実装できるようにするために、これまでに持っていたすべてのもの(つまり、リストビュー)をパーシャルと呼ばれるものに移動しました。 パーシャルは基本的に、別の場所(まもなく)に含めるテンプレートコードのチャンクです。

次に、スキルをクリック可能にし、クリックすると、対応するスキルビューに移動します。 このために、プロキシイベントと呼ばれるものを使用します。これにより、物理イベントに反応し(クリックすると、名前はRactiveが理解できる名前になります)、論理イベントにプロキシします(select-skill、名前は私たちが呼ぶものです)。 )引数を渡します(おそらく覚えていると思いますが、これはここでのスキル名を表します)。

(参考までに、同じことを実行するためのメソッド呼び出しの代替構文が存在します。)

次に、(再び)選択したスキルの名前(存在する場合)を持つcurrentSkillという変数があるか、スキルが選択されていない場合は空になると想定します。 そのため、現在のスキル名を示す別のパーシャルを定義し、スキルの選択を解除する「CLOSE」リンクもあります。

JavaScriptの場合、主な追加は、select-skillイベントとdeselect-skillイベントをサブスクライブし、それに応じてcurrentSkill (およびskillFilter )を更新するコードです。

 var app = new Ractive({ el: '#root', template: '#tpl-app', data: { skillFilter: null, currentSkill: null, // INITIALIZE currentSkill TO null // skills function remains unchanged skills: function() { var skillFilter = this.get('skillFilter'); if (!skillFilter) { return skillNames; } skillFilter = new RegExp(_.escapeRegExp(skillFilter), 'i') return _.filter(skillNames, function(skill) { return skill.match(skillFilter); }); } } }); // SUBSCRIBE TO LOGICAL EVENT select-skill app.on('select-skill', function(event, skill) { this.set({ // SET currentSkill TO THE SKILL SELECTED BY THE USER currentSkill: skill, // RESET THE SEARCH FILTER skillFilter: null }); }); // SUBSCRIBE TO LOGICAL EVENT deselect-skill app.on('deselect-skill', function(event) { this.set('currentSkill', null); // CLEAR currentSkill });

各スキルの開発者のリスト

スキルの新しいビューを準備したら、肉を追加できます。これは、そのリストに含まれる開発者の実際のリストです。 そのために、このビューの部分を次のように展開します。

 {{#partial skillView}} <h2> {{ currentSkill }} <button type="button" class="close pull-right" on-click="deselect-skill">&times; CLOSE</button> </h2> {{#each skillDevelopers(currentSkill)}} <div class="panel panel-default"> <div class="panel-body"> {{ this.name }} </div> </div> {{/each}} {{/partial}}

この時点で、ここで何が起こっているのかを理解できればskillViewパーシャルに新しい反復セクションを追加し、次に作成する新しいskillDevelopers関数の結果を反復処理します。 配列内の各開発者(そのskillDevelopers関数によって返される)について、パネルをレンダリングし、開発者の名前を表示します。 ここで暗黙の形式{{name}}を使用でき、Ractiveは現在のコンテキスト(この場合は{{#each}}でバインドされた開発者オブジェクト)から始まるコンテキストチェーンを検索することで適切な属性を見つけることに注意してください。私は明示的であることを好みます。 コンテキストとリファレンスの詳細については、Ractiveのドキュメントを参照してください。

そして、 skillDevelopers()関数の実装は次のとおりです。

 skillDevelopers: function(skill) { // GET THE SKILL OBJECT FROM THE “DB” skill = skills[skill]; // SAFETY CHECK, RETURN EARLY IN CASE OF UNKNOWN SKILL NAME if (!skill) { return; } // MAP THE DEVELOPER'S IDs (SLUGS) TO THE // ACTUAL DEVELOPER DETAIL OBJECTS return _.map(skill.developers, function(slug) { return developers[slug]; }); }

各開発者のエントリを拡張する

開発者の作業リストができたので、詳細を追加します。もちろん、素敵な写真を追加します。

 {{#partial skillView}} <h2> {{ currentSkill }} <button type="button" class="close pull-right" on-click="deselect-skill">&times; CLOSE</button> </h2> {{#each skillDevelopers(currentSkill)}} <div class="panel panel-default"> <div class="panel-body media"> <div class="media-left"> <!-- ADD THE PHOTO --> <img class="media-object img-circle" width="64" height="64" src="{{ this.photo }}" alt="{{ this.name }}"> </div> <div class="media-body"> <!-- MAKE THE DEVELOPER'S NAME A HYPERLINK TO THEIR PROFILE --> <a class="h4 media-heading" href="{{ this.url }}" target="_blank"> {{ this.name }}</a> <!-- ADD MORE DETAILS (FROM THEIR PROFILE) --> <p>{{ this.desc }}</p> </div> </div> </div> {{/each}} {{/partial}}

ここでは、Ractive側から新しいことは何もありませんが、Bootstrap機能の使用量が少し多くなっています。

クリック可能な開発者スキルのリストの表示

これまでのところ順調に進んでいますが、まだ欠けている機能の1つは、スキルと開発者の関係の反対側です。 つまり、各開発者のスキルを表示し、それらの各スキルを、そのスキルの結果ビューに移動するためのクリック可能なリンクにする必要があります。

しかし、待ってください…私たちはすでにスキルリストにまったく同じものがあると確信しています。 はい、実際、私たちはそうします。 それはクリック可能なスキルのリストにありますが、それは各開発者のスキルのセットとは異なる配列から来ています。 しかし、これらは十分に類似しているため、HTMLのそのチャンクを再利用する必要があることは明らかです。 そしてそのために、パーシャルは私たちの友達です。

(注:Ractiveには、コンポーネントと呼ばれる、ビューの再利用可能なチャンクに対するより高度なアプローチもあります。これらは非常に便利ですが、簡単にするために、ここでは説明しません。)

したがって、パーシャルを使用してこれを実現する方法は次のとおりです(ちなみに、JavaScriptコードを1行追加しなくても、この機能を追加できることに注意してください)。

 <!-- MAKE THE CLICKABLE SKILL LINK INTO ITS OWN “skill” PARTIAL --> {{#partial skill}} <a href="#" class="label label-primary" on-click="select-skill:{{this}}">{{this}}</a> {{/partial}} {{#partial skillsList}} <div class="row"> <form class="form-horizontal col-xs-6 col-xs-offset-6"> <input type="search" class="form-control" value="{{ skillFilter }}" placeholder="Type part of the skill name here"> </form> </div> <hr> <div class="row"> {{#each skills()}} <!-- USE THE NEW “skill” PARTIAL --> <span class="col-xs-3">{{> skill}}</span> {{/each}} </div> {{/partial}} {{#partial skillView}} <h2> {{ currentSkill }} <button type="button" class="close pull-right" on-click="deselect-skill">&times; CLOSE</button> </h2> {{#each skillDevelopers(currentSkill)}} <div class="panel panel-default"> <div class="panel-body media"> <div class="media-left"> <img class="media-object img-circle" width="64" height="64" src="{{ this.photo }}" alt="{{ this.name }}"> </div> <div class="media-body"> <a class="h4 media-heading" href="{{ this.url }}" target="_blank">{{ this.name }}</a> <p>{{ this.desc }}</p> <p> <!-- ITERATE OVER THE DEVELOPER'S SKILLS --> {{#each this.skills}} <!-- REUSE THE NEW “skill” PARTIAL TO DISPLAY EACH DEVELOPER SKILL AS A CLICKABLE LINK --> {{> skill}}&nbsp; {{/each}} </p> </div> </div> </div> {{/each}} {{/partial}}

「DB」から取得した開発者のオブジェクトにスキルリストが添付されているので、テンプレートを少し変更しました。スキルラベルをレンダリングする行をパーシャルに移動し、その行が元々あった場所でこのパーシャルを使用しました。

次に、開発者のスキルを繰り返すときに、この同じ新しいパーシャルを再利用して、これらの各スキルをクリック可能なリンクとして表示することもできます。 さらに、覚えていれば、これは選択スキルイベントをプロキシし、同じスキル名を渡します。 これは、これをどこにでも(適切なコンテキストで)含めることができ、スキルビューにつながるクリック可能なラベルを取得することを意味します!

ファイナルタッチ—プリローダー

これで、基本的な機能アプリができました。 クリーンで高速に動作しますが、ロードにはまだ時間がかかります。 (私たちの場合、これは部分的に連結されていない、縮小されていないソースを使用しているためですが、実際のアプリでは、初期データのロードなど、他の重要な理由が考えられます)。

最後のステップとして、Ractiveがアプリをレンダリングするとすぐに削除されるプリロードアニメーションを追加するための巧妙なトリックを紹介します。

 <div class="container"> <h1>Toptal Search</h1> <div> <div class="progress"> <div class="progress-bar progress-bar-striped active"> Loading... </div> </div> </div> </div>

それで、ここの魔法は何ですか? 実はとても簡単です。 ルート要素にいくつかのコンテンツ(Bootstrapアニメーションのプログレスバーですが、アニメーションGIFなど)を直接追加しました。 スクリプトの読み込み中、ユーザーには読み込みインジケーターが表示されます(JavaScriptに依存していないため、すぐに表示できます)。 ただし、Ractiveアプリが初期化されるとすぐに、Ractiveはルート要素のコンテンツを上書きし(したがって、プリロードアニメーションを消去し)、レンダリングされたテンプレートを使用します。 このようにして、静的HTMLの一部と0行のロジックだけでこの効果を実現できます。 かっこいいと思います。

結論

ここで私たちが達成したことと、それをどれほど簡単に達成したかを考えてください。 非常に包括的なアプリがあります。スキルのリストが表示され、スキルをすばやく検索でき(ユーザーが検索ボックスに入力すると、スキルリストのインタラクティブな更新もサポートされます)、特定のスキルに移動したり戻ったりできます。選択した各スキルの開発者。 さらに、任意の開発者によってリストされた任意のスキルをクリックして、そのスキルを持つ開発者のリストに移動できます。 そして、80行未満のHTMLと40行未満のJavaScriptですべてを実現します。 私の考えでは、それは非常に印象的であり、Ractiveのパワー、エレガンス、シンプルさについて多くを語っています。

アプリの動作バージョンはここからオンラインで入手でき、完全なソースコードは公開されており、ここから入手できます。

もちろん、この記事では、Ractiveフレームワークで何が可能かについての表面をかろうじてかじっただけです。 これまでに見たものが気に入った場合は、Ractiveの60秒のセットアップを開始し、Ractiveが提供するすべての機能を自分で調べ始めることを強くお勧めします。