vue.js + vuexでの開発を支援する5つのトリック

最近、 vue.jsを扱うことにしました。 テクノロジーを学ぶ最良の方法は、テクノロジーに何かを書くことです。 この目的のために、私の古いルートプランナーは書き直されました。 これはそのようなプロジェクトの結果です 。 コードは、スケーリングのタスクに直面するのに十分な大きさであることが判明しました。



この記事では、私の意見では、主要なプロジェクトの開発に役立つ多くの手法を紹介します。 vue.js + vuexでtodoシートをすでに作成しているが、主要な自転車の構造にまだ埋まっていない場合、この資料が役立ちます。







1.集中イベントバス



vue.jsのプロジェクトは、ネストされたコンポーネントで構成されています。 基本原則は、小道具を下げ、イベントを上げることです。 サブコンポーネントは、変更できない親からデータを受け取り、トリガーできる親イベントのリストを受け取ります。



原則は有効ですが、強力な接続性を作成します。 ターゲットコンポーネントが深く埋め込まれている場合、すべてのラッパーを通してデータとイベントをドラッグする必要があります。



イベントに対処します。 多くの場合、階層に関係なく、任意のコンポーネントが通信できるグローバルイベントエミッターがあると便利です。 これは非常に簡単で、追加のライブラリは必要ありません。



Object.defineProperty(Vue.prototype,"$bus",{ get: function() { return this.$root.bus; } }); new Vue({ el: '#app', data: { bus: new Vue({}) // Here we bind our event bus to our $root Vue model. } });
      
      





その後、これにアクセスします。$バスは任意のコンポーネントに表示され、これを介してイベントをサブスクライブできます。$バス。$オン()およびこれを介してそれらを呼び出します。$バス。$放出()。 以下に例を示します。



これを理解することは非常に重要です$ Busはアプリケーション全体のグローバルオブジェクトです。 登録解除を忘れた場合、コンポーネントはこのオブジェクトのメモリに残ります。 したがって、各this。$ Bus。$マウントされた状態で対応するthis。$ Bus。$ beforeDestroyでオフになっている必要があります。 たとえば、次のように:



 mounted: function() { this._someEvent = (..) => { .. } this._otherEvent = (..) => { .. } this.$bus.$on("someEvent",this._someEvent); this.$bus.$on("otherEvent",this._otherEvent); }, beforeDestroy: function() { this._someEvent && this.$bus.$off("someEvent",this._someEvent); this._otherEvent && this.$bus.$off("otherEvent",this._otherEvent); }
      
      





2.中央集権型バス



コンポーネントでは、他のコンポーネントからアクセスする何らかの非同期のもの(たとえば、Googleマップインスタンス)を初期化する必要がある場合があります。 これを行うには、プロミスを保存するオブジェクトを整理します。 たとえば、 そのような 。 イベントバスの場合と同様に、コンポーネントが初期化されていないときに削除することを忘れないでください。 一般に、上記の方法で、vueに任意のロジックを持つ任意の外部オブジェクトをアタッチできます。



3.平らな構造(平らな店)



複雑なプロジェクトでは、データは頻繁にネストされます。 このようなデータの操作は、vuexとreduxの両方で不便です。 たとえば、 normalizrユーティリティを使用して、ネストを減らすことをお勧めします。 ユーティリティは優れていますが、それが何をするかを理解することはさらに良いことです。 私はすぐにフラットな構造を理解するようになりませんでした。同じタイプの自分のために、詳細な例を検討します。



プロジェクトは、それぞれに-レイヤーの配列、各レイヤーに-ページの配列にあります:プロジェクト>レイヤー>ページ。 ストレージを整理する方法は?



最初に思い浮かぶのは、通常のネストされた構造です。



 projects: [{ id: 1, layers: [{ id: 1, pages: [{ id: 1, name: "page1" },{ id: 2, name: "page2" }] }] }];
      
      





この構造は読みやすく、プロジェクトでforeachサイクルを実行しやすく、レイヤーのリストを使用してサブコンポーネントをレンダリングしやすいなどです。 しかし、idでページの名前を変更する必要があるとします:1。 ページをレンダリングする小さなコンポーネント内で、$ store.dispatchが呼び出されます( "changePageName"、{id:1、name: "new name"})。 この深くネストされた構造内で、IDが1の目的のページがある場所を見つける方法は? ストア全体を実行しますか? 最良の解決策ではありません。



次のようなフルパスを指定できます。



 $store.dispatch("changePageName",{projectId:1,layerId:1,id:1,name:"new name"})
      
      





ただし、これは、ページレンダリングのすべての小さなコンポーネントで、projectIdとlayerIdの両方の階層全体をドラッグする必要があることを意味します。 不便。



sqlからの2回目の試行:



 projects: [{id:1}], layers: [{id:1,projectId:1}], pages: [{ id: 1, name: "page1", layerId: 1, projectId: 1 },{ id: 2, name: "page2", layerId: 1, projectId: 1 }]
      
      





これで、データを簡単に変更できます。 しかし、実行するのは難しいです。 すべてのページを1つのレイヤーに表示するには、一般にすべてのページを実行する必要があります。 これは、ゲッターまたはテンプレートのレンダリングで非表示にできますが、まだ実行されます。



3番目の試み、normalizrアプローチ:



 projects: [{ id: 1, layersIds: [1] }], layers: { 1: { pagesIds: [1,2] } }, pages: { 1: {name:"page1"}, 2: {name:"page2"} }
      
      





レイヤーのすべてのページは、簡単なゲッターを介して取得できます



 layerPages: (state,getters) => (layerId) => { const layer = state.layers[layerId]; if (!layer || !layer.pagesIds || layer.pagesIds.length==0) return []; return layer.pagesIds.map(pageId => state.pages[pageId]); }
      
      





ゲッターはすべてのページのリストを実行しないことに注意してください。 データは簡単に変更できます。 レイヤー内のページの順序はレイヤーオブジェクトで指定され、これも正しいです。再ソート手順は通常、オブジェクトのリストを表示するコンポーネント(この場合はレイヤーをレンダリングするコンポーネント)で行われるためです。



4.突然変異は必要ありません



vuexルールによると、ストレージデータの変更はミューテーション関数でのみ発生し、ミューテーションは同期的である必要があります。 Vuexには、メインアプリケーションロジックが含まれています。 したがって、データ検証ブロックも論理的にリポジトリに含めることができます。



ただし、検証は常に同期とはほど遠いものです。 したがって、検証ロジックの少なくとも一部は突然変異ではなく、アクションに含まれます。



私は、ロジックを壊さず、すべての検証をアクション全般に​​保存することを提案します。 突然変異は、基本的な割り当てで構成されるプリミティブになります。 ただし、アプリケーションから直接アクセスすることはできません。 すなわち 変異はリポジトリ内の一種の実用的なものであり、vuexデバッガーにのみ有用です。 アプリケーションは、アクションのみを介してリポジトリと通信します。 私のアプリケーションでは、同期であっても、アクションは常にプロミスを返します。 何が何であるかを覚えるよりも簡単に、すべてのアクションを非同期と見なすこと(および約束として動作すること)が簡単であるように思えます。



5.反応性の制限



ストレージ内のデータが変更されない場合があります。 たとえば、外部APIからリクエストされた、マップ上のオブジェクトの検索結果にすることができます。 各結果は、多くのフィールドとメソッドを持つ複雑なオブジェクトです。 結果のリストを表示する必要があります。 反応性リストが必要です。 ただし、オブジェクト自体の内部のデータは一定であり、各プロパティの変更を追跡する必要はありません。 反応性を制限するには、Object.freezeを使用できます。



しかし、私はより愚かな方法を好みます。状態にid-shniksのリストのみを保存させ、結果自体が配列内に並んでいるようにします。 タイプ:



 const results = {}; const state = {resultIds:[]}; const getters = { results: function(state) { return _.map(state.resultsIds,id => results[id]); } } const mutations = { updateResults: function(state,data) { const new = {}; const newIds = []; data.forEach(r => { new[r.id] = r; newIds.push(r.id); }); results = new; state.resultsIds = newIds; } }
      
      





ご質問



私が望んでいたほど美しくはなかった何か。 コミュニティに対する私の質問は次のとおりです。



-不透明度を変更するよりもCSSアニメーションを倒す方法は? 多くの場合、未知のサイズのブロックの外観をアニメーション化する必要があります。 高さをheight:0からheight:autoに変更します。

これはjavascriptで簡単に解決できます-オーバーフローでコンテナにラップするだけです:隠し、ラップされた要素の高さを見て、コンテナの高さをアニメーション化します。 これはcssで解決できますか?



-webpackのアイコンを操作する通常の方法を探していますが、これまでのところ失敗しています(したがって、fontelloを使用し続けています)。 Whhgアイコンのような。 svgを引き出し、ファイルに分割しました。 複数のファイルを選択し、ファイル名に基づいてインラインでフォント+クラスを自動的にアセンブルしたいと思います。 これをどのように行うことができますか?



All Articles