Reactjsガンマジェネレーター

こんにちは、harazhiteli!



少し前まで、facebook- Reactjsからユーザーインターフェイスを構築するためのJavaScriptライブラリがインターネットに登場しました。 このライブラリは、単純および複雑なJavaScriptアプリケーションを作成するのに最適です。 クライアント側を独立したコンポーネントとして整理できます。 ツリーのDOM構造の変更を処理します。 そして、これを非常に効率的かつ合理的に行います。



一般に、reactjsに少し精通している結果、そのようなアプリケーションが登場しました-demo この投稿の目的は、reactjs + gruntjs + browserifyで作業した印象を共有することです。



以下が記載されます。







猫をお願いしたい人は...





アプリケーションのアイデア


私は誘惑されることはありません。オンラインガンマジェネレーターのアイデアは新しいものではありません。このリソースからインスピレーションを得て、自分からいくつかのグッズを追加しました。 ガンマは、主に即興演奏を習得しようとしている人々に役立ちます。 そして、ゲームのテクニックを改善するためのエクササイズと同じくらい便利です。 実際、各音階は、特定の式に従って計算される特定の音符で構成されています。 ギター愛好家として、調性を推測し、お気に入りの音楽に合わせてソロを選んでみてください。 そして、このアプリケーションはこれを非常によく助けます。



実装されたもの




  1. 調性の選択。
  2. ガンマ選択(マイナー、メジャー、ブルース、ペンタトニック)。
  3. ギターシステムの選択。
  4. ギターネックの選択したセクションの音を交互に演奏します。
  5. ノートの方向を変更します(上から下/下から上)。
  6. 周期的な再現の可能性(記憶のため)。
  7. 音符の方向を自動的に変更します。




アプリケーション構成


良いカルマのために、私はそれをいじりたいです-すべてのjavascriptはcommonjsモジュールとして設計され、1つのファイルに接着され、縮小されてreactjsコンポーネントがアセンブリ中にレンダリングされ、htmlページに挿入されます。

この効果は、次のツールを使用して達成されました。



commonjs形式は非常に便利で、サーバーとクライアントの両方で同じjavascriptコードを使用できます。



サーバーの事前レンダリング


私にとってreactjsの最も魅力的な機能の1つは、サーバー側のコンポーネントレンダリングの可能性です。 結局のところ、アプリケーションの初期状態を初期化し、ブラウザに到達する前にコンポーネントを描画できるのは素晴らしいことです。 reacjsの優れた点は、コンポーネントが既にレンダリングされていることを理解し、それを再試行しないことです。 demoのページコードを見ると、コンテンツがブラウザに送信される前に、ページのメインコンポーネントが既に描画されていることがわかります。 サーバーレンダリングの主な要件は、サーバー上にrequireコンポーネントを作成できることです。 事前レンダリング手順はデプロイメント中にのみ必要であるため、gh-pages- grunt-react-renderにアップロードする前にhtmlファイルを処理する個別のgruntプラグインを作成することにしました。

プラグインは非常にシンプルで、このアルゴリズムに従って動作します。



  1. 処理のためにファイルを読み取ります。
  2. html構造を解析すると、data-rcomp属性を持つタグが見つかります。
  3. data-rcomp属性からコンポーネントへの相対パスを読み取ります。
  4. コンポーネントを必須にし、react.renderComponentToString()メソッドを呼び出します。
  5. data-rcomp属性を使用してタグ内に挿入します。
  6. ファイルを保存します。




このプラグインが処理するメインページのhtmlセクションは次のとおりです。

<div class="container"> <h1>Scales generator</h1> <div data-rcomp="./lib-js/pages/scales_page_component" id="container"> </div> </div>
      
      







これは、うなり声のプラグイン設定がどのように見えるかです:



  react_render: index: options: src: '.dist/index.html'
      
      







Reactjsインプレッション


Reactjsは、可能であれば再利用可能な個別の構成可能なコンポーネントの形でアプリケーションロジックを形成することを推奨します。 reactjsの哲学では、さまざまな場所に保存された状態は魔法と副作用の原因になるため、コンポーネントは状態を最小限に抑える必要があると述べています。 したがって、最上位コンポーネントの状態を保存して変更し、プロパティ(プロパティ)を介して内部コンポーネントに渡すことをお勧めします。



アプリケーションを作成する過程で、インターネット上の単純なコンポーネントに対する既製のソリューションがほとんどないという事実に出会いました。 最初、私は非常に混乱し、同じドロップダウンリストなどの既製のソリューションを探していました。 それらをプロジェクトに統合してレイアウトを調整しようとしましたが、そのようなドロップダウンリストの機能をゼロから実装しようとしました。

画像



そして、reactjsがいかに簡単であるかに驚きました。 実際、すべてのレンダリングがreactjsで行われる場合、コンポーネントは非常に単純になり、コンポーネントを異なる状態でレンダリングして正しく切り替える方法を指定するだけで済みます。



ドロップダウンコード
 React = require 'react' {ul, li, span, div, a} = React.DOM SimpleDropdown = React.createClass displayName: "SimpleDropdown" getDefaultProps: -> onChange: -> getInitialState: -> isOpen: false value: @props.value or "" toggle: -> @setState {isOpen: !@state.isOpen} itemClick: (ev) -> ev.preventDefault() value = (ev.target.getAttribute "value") @setState {value, isOpen: false} @props.onChange value render: -> self = @ options = @props.options.map ([value, text]) -> (li {key: "opt_#{value}"}, (a {value, href: "#", onClick: self.itemClick}, text)) openCls = if @state.isOpen then "open" else "" currentOption = (@props.options.filter ([value, text]) => value.toString() is @state.value.toString())?[0] (div className: "btn-group #{openCls}" (button className: "btn btn-default" onClick: @toggle (span {className: "glyphicon"}, "") currentOption?[1] (span {className: "caret"}, "")) (ul className: "dropdown-menu" ref: "select" options))
      
      







Coffeescriptは、コンポーネントのhtml構造を記述するのに非常に便利であることが判明しました。 その再構築の割り当ては特に便利です。



 {div, ul, span, li} = React.DOM (div {className: "div"} (span {className: "span", "span Text") (ul (li "option 1") (li "option 2") )
      
      







私に関しては、 jsxを使用しなくても十分です 。 また、ブートストラップボタンとドラッグ可能なコンポーネントの動作をいじる必要がありました。



ビジネスロジック


このアプリケーションは、反応をマスターするためだけでなく、ギターの音階を研究するために他の人の生活を簡素化するために作成されたため、可能な限り誰かが簡単に別の音階またはシステムを追加できるように、すべてのロジックを可能な限りシンプルにしようとしましたギター。 したがって、たとえば、コード内のガンマの説明は次のようになります。

 SCALES = Minor: desc: "Minor scale" size: [STEP, hSTEP, STEP, STEP, hSTEP, STEP, STEP] get_notes: (Tonica) -> generate_scale Tonica, SCALES.Minor Major: desc: "Major scale" size: [STEP, STEP, hSTEP, STEP, STEP, STEP, hSTEP] get_notes: (Tonica) -> generate_scale Tonica, SCALES.Major ...
      
      





各ガンマには、独自の式(サイズ)、メモと説明を生成する関数があります。 このプロジェクトを1人の友人に見せた彼は、音楽に深い知識を持ち、難なく他のいくつかの尺度を追加しました。



ギターの弦のデータは次のように単純です。

 TUNINGS = "Standart": name: "Standart E" notes: [E, B, G, D, A, E] offset: [0, 0, 0, 0, 0, 0] "DropD": name: "Dropped D" notes: [E, B, G, D, A, D] offset: [0, 0, 0, 0, 0, -2] ...
      
      







サウンドの代替再生は、 howler.jsライブラリを使用して実装されます。

この場所を読んだ人の誰かがプロジェクトに何かを追加して改善したいという願望を持っているなら、私はそれについて非常に幸せです。



最初のチームを構築して展開する


多くは、プロジェクトのアセンブリとコードの編成にまったく気にしません。おそらくこれは正しいでしょう。 個人的には、自動化プロセスに喜びを感じているので、これについて少し混乱し、gruntjsでプロジェクトのアセンブリと展開を整理しました。 3つの主なコマンドがあります。



リポジトリ内の Gruntfileを使用すると、プロジェクトの構築に関する詳細を確認できます。



結論


一般に、reactjsを使用した作業には好印象がありましたが、将来的にはFRPライブラリ(RxJsまたはbacon.js)と一緒に試してみたいと思います。 また、このプロジェクトに他の便利な機能を追加する予定です。

ご清聴ありがとうございました! 批判、希望、フィードバックを歓迎します。



ソースコード-github



All Articles