同型BEM

node.jsが登場したとき、多くのWeb開発者は、クライアントとサーバーの両方で同じコードを使用する可能性について考え始めました。 現在、「コードを一度書くだけで、どこでも使用する」アプローチを最前線に置くいくつかのフレームワークがあり、新しいものがときどき登場します。 だから私は通り過ぎることができなかった、私は同様のマイクロフレームワーク-bnsfを書く 。 適切なテクノロジーとツールのセットを使用して、BEM手法に従ってアプリケーションのフロントエンドを作成することを好むユーザーを対象としています。



bnsfを使用して、簡単な1ページのWebアプリケーションのフロントエンドの記述を開始してみましょう。 バックエンド部分の作成に気を取られないように、vk.com APIをバックエンドとして使用します。 このアプリケーションは、メインページ(識別子によるユーザー検索フォームを含む)と、2ページ目のみで構成され、選択したユーザーに関する情報を表示します。



開始するには、node.js、yeoman、gulpが必要です。 理論的には動作するはずですが、コードはWindowsでテストされていないため、* nix OSの使用をお勧めします。 node.jsが既にインストールされていると仮定します。 そうでない場合は、 nvmを使用することをお勧めします。



gulp、yeoman、および対応するジェネレーターをインストールします。



npm install -g gulp yo generator-bnsf
      
      





プロジェクトを作成します。



 yo bnsf vk-test-app cd vk-test-app
      
      





生成されたファイルとフォルダーを確認できます。



 ls
      
      





次の一連のファイルのようなものを出力します(順序はオペレーティングシステムによって異なる場合があります)。



 README.md desktop.blocks gulpfile.js node_modules bower.json desktop.bundles libs package.json
      
      





プロジェクトは既に組み立てを試みることができます:



 gulp
      
      





gulpはプロジェクトを組み立てるだけでなく、サーバーを起動し、プロジェクトの変更を監視し始め、必要に応じて再構築します。



すべてが機能することを確認します。 ブラウザでhttp:// localhost:3000を開こうとします-テキストpage-indexとメインページのタイトルを含むページが表示されます。



すでに1つのページがあります。ユーザーのウォールからの投稿を表示する2番目のページを作成しましょう。 これを行うには、再びジェネレーターが必要です。 コマンドラインから機能するため、gulpを中断しないように別のターミナルセッションが必要です。 この時点で、ヨーマンが尋ねるすべてのものに単純に同意することができます。 競合を警告します-これは、ファイルを新規作成せず、既存のファイルを編集する場合の標準的な方法です。すべての質問に答えてEnterキーを押すだけです。 それでは、プロジェクトのルートから実行してみましょう。



 yo bnsf:page user
      
      





もう一度お知らせします。すべての質問に同意して答えます。つまり、入力を押します。



gulpは、新しいページの外観に気付き、プロジェクトを再構築します。 チェック: httpのリクエスト:// localhost:3000 /ユーザーは、テキストpage-userのページを返す必要があります。



次のようにdesktop.blocks/page-index/page-index.bemtree



を編集して、メインページに検索フォームを配置しましょう。



 block('page-index')( content()(function () { return [ { block: 'search-form', content: [ { block: 'input', mods: { theme: 'simple' } }, { block: 'button', mods: { type: 'submit', theme: 'simple' }, content: 'search' } ] }, { block: 'search-results' } ]; }) ); block('page-index').elem('title').content()('main page');
      
      





そして、それに応じてpage-index.deps.js:



依存関係を変更しpage-index.deps.js:







 ({ mustDeps: ['i-page'], shouldDeps: [ { elem: 'title' }, 'search-form', { block: 'input', mods: { theme: 'simple' } }, { block: 'button', mods: { theme: 'simple' } }, 'search-results' ] })
      
      





これで、フォームはすでに表示されています( http:// localhost:3000に再度アクセスして確認できます)。タグはform



ではなくdiv



です。 これを修正するには、適切なテンプレートファイルdesktop.blocks/search-form/search-form.bemhtml



ます。



 block('search-form').tag()('form');
      
      





これで、コードを1行だけ保存するファイルを含む別のディレクトリを作成することは冗長に思えるかもしれません。 しかし、実際のプロジェクトでは、これを満たすことはほとんど不可能です。スタイルやJavaScriptを含むファイルが必ず表示されるか、ブロックテンプレート自体がより複雑になります。 多くの場合、上記のすべてがすぐに。



まあ、私たちはフォームを持っていますが、それでも何かを探す方法を知りません。 フォームの観点から「検索」してみましょう-クエリパラメータで現在のページにリダイレクトします。 フォームがこれを開始するには、 desktop.blocks/search-form/search-form.browser.js



次のJSが必要desktop.blocks/search-form/search-form.browser.js







 /**@module search-form*/ modules.define('search-form', ['i-bem__dom', 'app-navigation'], function (provide, BEMDOM, navigation) { "use strict"; /** * @class SearchForm * @extends BEM.DOM * @exports */ provide(BEMDOM.decl(this.name, /**@lends SearchForm#*/{ onSetMod: { js: { /** * @constructs * @this SearchForm */ inited: function () { this._input = this.findBlockInside('input'); } } }, /** * @param {Event} e * @private */ _onSubmit: function (e) { e.preventDefault(); var query = this._input.getVal(), params = query ? {query: query} : null; navigation.navigate('page-index', params); } }, /**@lends SearchForm*/{ /** * @static */ live: function () { var init = { modName: 'js', modVal: 'inited' }; this .liveInitOnBlockInsideEvent(init, 'button') .liveInitOnBlockInsideEvent(init, 'input') .liveBindTo('submit', function (e) { this._onSubmit(e) }); } })); });
      
      





また、ブロックにロジックがあるという情報、ファイルdesktop.blocks/search-form/search-form.bemhtml



追加して、テンプレートを少し複雑にする必要があります。



 block('search-form')( tag()('form'), js()(true) );
      
      





これで、ページのgetパラメーターを変更できるフォームができました。 これを確認するには、テキスト入力に「1」と入力してEnterキーを押します。 このパラメータに関するデータを取得する時が来ました。 認証を必要とするAPIを使用したくないので、URLで誰でも使用できるメソッドを使用します api.vk.com/method/users.get



api.vk.com/method/users.get



フォームがユーザー識別子を受け入れると、リンクがそのページ(上で作成したユーザーページ)と、単純な増分で取得された識別子を持つ4人のユーザーのページに表示されます。 リンクのテキストとして、ユーザー名を使用します。



最初に行う必要があるのは、APIルート構成ファイルにルートを追加することです。 これはファイルdesktop.bundles/index/index.api.routing.yml



であり、その内容は次のdesktop.bundles/index/index.api.routing.yml







 - host: api.vk.com routes: - id: users path: /method/users.get
      
      





2番目desktop.blocks/search-results/search-results.bemtree



ファイルを作成します。 主なアイデアはこれです:誰がデータを表示する必要があるか、彼はそれらを追いかけます。 この場合、データはsearch-resultsブロックに必要であり、データの後に行く必要があります。



 block('search-results').content()(function () { if (!this.route.parameters.query) { return ''; } var id = parseInt(this.route.parameters.query, 10); return id ? this.get('users', { //      API   user user_ids: [id, id + 1, id + 2, id + 3, id + 4] }, function (data) { //       return data.body.response.map(function (dataItem) { return { block: 'search-results', elem: 'item', content: { block: 'link', url: path('page-user', { id: dataItem.uid }), //  url     page-user content: dataItem.first_name + ' ' + dataItem.last_name } }; }); }) : 'Something goes wrong'; });
      
      





このデータテンプレートでは、idが到着したかどうかを確認し、到着した場合は、getメソッドを使用してユーザーIDとuser_idsパラメーターを使用してAPIルートに沿ってデータを要求します。 idが数値でない場合は、「何かがおかしい」という文字列を指定します。 リストを表示する必要があり、セマンティクスが大好きなので、 desktop.blocks/search-results/search-results.bemhtml



作成します:



 block('search-results') .tag()('ul') .elem('item').tag()('li');
      
      





さらに、ブロックの依存関係を宣言するためのファイルdesktop.blocks/search-results/search-results.deps.js



です。



 ({ shouldDeps: ['link'] })
      
      





これで、ページはすでにユーザーを検索して結果を表示できます。 試してください。ページを更新することを忘れないでください。 「1」を入力すると、結果にPavel Durovが表示されます。 しかし、問題は、ページ全体が再描画されるたびに発生することです。 これは、必要なものだけを更新するように彼女に教えることで簡単に修正できます。 次のようにpage-index.bemtree



page-index.bemtree







 block('page-index')( content()(function () { return [ { block: 'search-form', content: [ { block: 'input', mods: { theme: 'simple' } }, { block: 'button', mods: { type: 'submit', theme: 'simple' }, content: 'search' } ] }, { block: 'search-results' } ]; }), js()({ update: 'search-results' //      JavaScript:  ,    }) ); block('page-index').elem('title').content()('main page');
      
      





これで、ブラウザでインスペクターを開くことで、APIへの新しいリクエストで、検索結果ブロックのみが更新されることを確認できます。



さて、2ページ目を作成する時が来ましたが、無駄ではありません。

desktop.blocks/page-user/page-user.bemtree



から始めましょう:



 block('page-user').content()(function () { return [ { block: 'menu', content: { block: 'link', url: path('page-index'), content: 'main page' } }, { block: 'user-card' } ]; }); block('page-user').elem('title').content()('user');
      
      





メインページへのリンク、リンク自体、およびユーザーに関する情報を表示するユーザーカードブロックのラッパーのように、偽のメニューブロックを追加しました。

desktop.blocks/page-user/page-user.deps.js



の依存関係を更新することを忘れないでください:



 ({ mustDeps: ['i-page'], shouldDeps: ['link', 'user-card'] })
      
      





実装するつもりはないので、それに応じてメニューブロックを追加しませんでした。



ユーザーカードを表示するには、ファイルdesktop.blocks/user-card/user-card.bemtree



作成します。



 block('user-card').content()(function () { return this.get('users', { user_ids: this.route.parameters.id }, function (data) { return data.body.response.map(function (dataItem) { var output = []; for (var key in dataItem) { if (dataItem.hasOwnProperty(key)) { output.push({ elem: 'row', content: [ { elem: 'key', content: key }, { elem: 'value', content: JSON.stringify(dataItem[key]) } ] }); } } return output; }); }); });
      
      





このフォームでは、すでに機能します。 検索結果のリンクをクリックしてみてください。その前にページを更新して、新しいコードを取得してください。 しかし、 desktop.blocks/user-card/user-card.bemhtml



定義して、ユーザーカードをテーブルにしましょう。



 block('user-card')( tag()('table'), elem('row').tag()('tr'), elem('key').tag()('td'), elem('value').tag()('td') );
      
      





まあ、それははるかに良いです。



少なくともユーザー入力の検証、より正確なURL、読み込みプロセスの表示、最後の検索への戻りを追加することはできますが、これを終了する時間だと思います。これは興味のある人のために宿題に任せます。 まあ、または次の記事は、興味のある人が尋ねたら。



便利なリンク:

bnsfは、記事で説明したフレームワークです。 実際には、BEM用語では単なるブロックのライブラリです。

bem-core -bnsfが依存するブロックライブラリ

bem-components-上記で作成されたプロジェクトで使用されるブロックライブラリ

bem.info-ドキュメントに関するbemに関するサイト。特に、以下について読むことができます。

bemtreeは、APIからのデータを使用して、テンプレートエンジンの入力を構築するためのテクノロジーです。

bemhtml-宣言型テンプレートエンジン

Nickolas Zackasによるトピック投稿。 翻訳があります。



All Articles