Vueを好きになったきっかけ

エントリー









この投稿は私の投稿/記事の論理的な続きです- どのようにAngularを 愛するのを止めたか / どのようにAngularを愛するのを止めたか

読む前に読むことをお勧めします。







約1年間、私が参加するすべてのプロジェクトで、AngularではなくVueを使用しています。

この投稿では、Angular後の主な印象と違いを共有し、戦闘プロジェクトでVueを使用した実際の経験からいくつかのことを説明します。







前の投稿の簡単な要約:



前回の記事を書いた時点でAngularで悩まされた主な問題の短いリストを以下に示します。







  1. 恐ろしいルーター
  2. ヘビーウェイトで実用的な無用の依存性注入(以下を参照)
  3. 非常に物議を醸すモジュールシステム(他のフレームワークでは使用されません)
  4. 多くの余分な、ほとんど有用な抽象化、奇妙なAPIデザイン
  5. フレームワークの一部として観察可能

    ...


DI



すぐに依存性注入について予約する必要があります。Vueに切り替えた後でも、Angularでは単体テストで外部依存性をウェット処理する方が便利であることに注意する価値があります。







コードベースと内部のベストプラクティスに完全に依存しますが、AngularよりもVueで何かを濡らすのが難しいことがよくあります(例を以下に示します)。







ただし、これがフロントエンドでこのような外部JavaScriptパターンを使用する重大な理由だとは思いません。







反応について



そして、ReactではなくVueが選ばれた理由に関するもう1つの小さな警告。

免責事項:以下のすべての点は非常に主観的です(したがって、それらは批判として受け取られるべきではなく、個人的な外観としてのみ取られるべきです):







  1. Vueでの反応性は、すぐに非同期で機能します。免疫機能やクリーンな機能を気にする必要はありません。

    (不変性の概念は非常にクールですが、しばしば非常に冗長です-ほとんどの場合、長くて高価です)
  2. JSXはいくつかの理由で一度に悪いです:

    • HTMLマークアップからアプリケーションコードへの移行が遅い-かなり些細なことに開発者を使用しなければならないデザイナーは、特にここで苦労します
    • 常に、特別な必要がなくても、すべてを小さなコンポーネントに分割する必要があり、Angular / VueでのVSテンプレート作成に時間がかかります-コンポーネントはいつでも必要に応じて取り出されます
    • 状態=痛みという新鮮な思い出がまだあります
  3. 地獄のフォーム-詳細は後で
  4. 私の意見では、 reate-react-app



    は、最も人気のあるすべてのフレームワークの中で最も機能性の低いCLIです。Reactは、はるかに強力なツールを作成する価値があります。
  5. 私たちのチームは、Angularを使ったかなり豊富な経験がありました。多くの同様の要因で、Vueに入るのがずっと簡単でした。


角度後の違いと印象



Vueに切り替えたときに気付いた主な違いと印象について少し説明します。







ドキュメント



UIフレームワークを選択するときに最初に出くわすのは、もちろんドキュメントです。







私はAngularドキュメントを再構築しません







箱入りバナナ

Vueでは、はるかに単純でわかりやすいとしか言​​えません。







例をあげません。なぜなら それらはすべてあなたにとって主観的なもののように思えるかもしれませんが、ドックを読み始めると、すぐに人々のために書かれたと感じます。







また、ドックが6言語で書かれていることも注目に値しますが、英語で十分です(現在、開発者は少なくとも読解レベルで英語を知っている必要があると思います)。







CLI



前回の記事から、Angular CLIが最高だと思っていたことがわかりましたが、結局のところ:







  1. カスタマイズ非常に難しい場合があります。
  2. AngularとCLIは、異なるバージョンの多くの@angular



    パッケージとCLIパッケージに分割されます。これは、CLI / angularバージョンをアップグレードするときに大きな問題につながります。

    すでに行われていることは簡単ではありません








一方、Vue CLI 3は今日で最もクールなCLIです。







  1. カスタマイズは非常に便利で、プラグインシステムのおかげで、いつでもパッケージを追加できます。
  2. webpackによるシンプルさと柔軟性








Zone.js対Vue Reactivity



AngularはZone.jsを使用して変更を追跡します。これは、 setTimeout



ような、この標準APIのパッチです。







これにより、特定の問題が発生します。







  1. 非標準APIの難しさ、時には解決が非常に難しい
  2. 恐ろしい痕跡
  3. 一般的に私見では、これはハックであり、最もエレガントなものからは程遠い


VueはZone.jsを必要としません。追跡は、すべてのデータ/状態プロパティをObserverに変換することで機能します。







ある時、ある種を見て、彼は魔法がなかったことに多少動揺していました。







最上位では、すべてが簡単です。VueはObject.definePropertyを介してすべてのプロパティを通過し(このためIE8以下はサポートされません)、ゲッターとセッターを追加します。







追加するものすらありません...







ただし、このアプローチには落とし穴がありますが、 説明非常に簡単で理解しやすいです。

さらに、理解はJS自体の中核であるVueほどではありません。







Vueでは、既存のインスタンスに新しいルートリアクティブプロパティを動的に追加することはできません。 ただし、Vue.set(オブジェクト、キー、値)メソッドを使用して、ネストされたオブジェクトにリアクティブプロパティを追加できます。


 var vm = new Vue({ data: { a: 1 } }) //  vm.a —   vm.b = 2 // vm.b   Vue.set(vm.someObject, 'b', 2)
      
      





バージョン2.6以降、Vueでもこれらの問題が発生しないことに注意してください。 プロキシへの移行が行われ、プロパティの追加/削除も追跡できるようになります。







Rxおよび状態管理



Angularでは、フレームワークの中核はRxJSであり、すべてがObservableです。

Rxに対する私の愛にもかかわらず、私と多くの人は、Rxが本当にAngular内で必要かどうかについて質問をしました。







特に最初は、多くの人が.toPromise()



を介してObservableを.toPromise()









とにかく、Angular自体の複雑さに加えて、一般的なデータバスのアイデアは理解するのが最も簡単ではありません。







同時に、Angularは非常に大規模なフレームワークであるため、現在最も人気のあるデータ管理パターンであるState Managementのすぐに使用可能な実装を提供しません。







NgRxがありますが 、それはそれほど前に完全に使用可能になりませんでした-結果として、Reduxのようなストアのカスタム実装を持つ古いプロジェクトさえあります。







そして今、Vueについて。







RxJSファンは、新しいパッケージを追加するだけで、いつでも簡単にプラグインできます。







すでにVue-Rxがあり 、データとともにRxJS Observabl'yを使用できます。







国家管理について話すと、素晴らしい公式Vuexがあります。

ある時、私は非常に驚いて、彼以外にも膨大な数の選択肢があることを発見しました。













立ち寄る



実際、これは主な利点(誰かに欠点があるように見えるかもしれませんが)がVueであるところです-必要に応じてすべてを接続できます。







追加するだけです:







  1. Rxjs
  2. ヴエックス
  3. TypeScript
  4. SCSS

    ...


不足していても、常に簡単かつ迅速に統合されます。







ルーター



Angularから受けた最も深刻な精神的損傷の1つの理由は、ルーターです。

彼はすでに3回対応しているという事実にもかかわらず、彼はまだひどいです (はい、私は繰り返します)。







彼のすべての問題を詳細に説明するわけではありませんが、このトピックは痛みを伴うので、簡単に説明します。







  1. 名前付きルートはありません(!)-最も奇妙な決定の1つは、名前付きルートを削除することでした。これにより、複雑なアプリケーションをサポートする利便性が低下することがありました。
  2. タイプごとに確認する必要がある奇妙なイベントシステム
  3. ルートパラメータをObservableに変換する-コンポーネントの起動時に1回だけ必要な場合、ルートパラメータを操作するのは非常に不便な場合があります
  4. ナビゲーションのために、 チームが考案されました。非常に奇妙であまり有用ではないソリューションであり、ルーターでは使用されなくなりました
  5. TypeScriptのみを使用したアプリケーションでのモジュールの文字列名による遅延読み込み...コメントなし

    ...など


並べ替えを見ると、これらの問題の多くがルーターの複雑さと機能に関連していることがわかります。







つまり、チームのように奇妙な決定がなくても、機能の数は依然として難しくなります。







Vueでは、ルーターは非常にシンプルで動作します。







簡単に言えば、Angularに精通しているabstract: true



パラメーターが一度も見つからなかったことに言及する必要があります。







テンプレートなしですぐにルートを作成することはできませんが、これは1行のコードで解決されます-次のようなコンポーネントを作成することにより







 // AbstractRoute.vue <template> <router-view/> </template>
      
      





そのような機能がすぐに使えるのは悪いことですか?







はい、いいえ。問題を簡単に解決できることが重要であり、一方で(Angularの策略とは対照的に)ルーター自体の複雑さと速度が重要だからです。







ところで、ここにクールなものがあります:







  path: `url/sub-url/:id', component: MyComponent, props: true
      
      





これで、コンポーネントMyComponent



にはprops



id



、これはURLからのパラメーターになります。

これはエレガントなソリューションです id



はすぐにリアクティブになり、コンポーネントで使用すると非常に便利です(再び機能します )。







拡張と再利用



一方では、AngularのすべてのコンポーネントはTypeScriptクラスです。

それにもかかわらず、多くのTypeScript チップを使用することは、しばしば不便または不可能です。







これは主にOOPに適用されます-継承、抽象クラス、スコープ。

主な問題は、依存性注入とAOTコンパイラーで発生します( それらに遭遇することは神が禁じています)。







Vueでは、インスタンス構成はオブジェクトです-簡単に操作して展開し、リファクタリングします。

コードを再利用するための強力なものがあります-ミックスインとプラグイン(これについては以下で詳しく説明します)。







UIコンポーネント



エンタープライズセグメントでは、コンポーネントには通常、完成したデザイン、モカパなどがあります。 ほとんどの場合、それらはゼロから作成され、特定のタスク/製品/プロジェクトのためにすぐにシャープ化されます。

しかし、いつまでもそうではないので、開発者は、特にペットプロジェクトやプロトタイピングのために、すべてをゼロから作成する機会があります。







ここでは、既製のUIコンポーネントのライブラリが役立ちます。Vueには、Element、Vuetify、Quasar、Vue-Material、Muse、iViewなど、すでに非常に多くのライブラリがあります。













特にElementとVuetifyについて言及します。印象は厳密にポジティブです。あらゆるニーズに対応する美しく安定したコンポーネント、優れたドックです。







また、 クールなBulma CSSフレームワークに基づいたBuefyコンポーネントセットも非常に気に入っています。サードパーティのコンポーネントが必要に応じて接続されるBulmaアプリケーションで使用すると特に便利です。







Angular-エンタープライズレベルのコンポーネントライブラリの場合、ほんの2、3個の断片であり、これらは主にAngular Material(Google)とClarity(VMWare)です。







残念ながら、Clarityの開発のペースは最近低下しました。これは、この問題に関するAngularの見通しに関してさらに苛立たしいものです。















実際の経験と問題



そして今、戦闘プロジェクトでVueを使用した実際の経験からの主な問題。







自由すぎる



深刻なプロジェクトの主な問題Vue、今日、私はあまりにも多くの選択の自由を呼びます。







一方では、同じことが多くの異なる方法で実行できるという事実は非常にクールです。







しかし、実際には、これはコードベースが非常に矛盾するという事実につながります。







誇張された例:ページ上のカスタムロジックは、コンポーネントを宣言することで作成でき、ローカルの場合もあります







 const Component = { created() { // logic ... }} new Vue({ components: [Component],
      
      





とてもグローバル(どこからでもアクセス可能)。







 Vue.component('Global', { created() { // logic ... }})
      
      





この機能を実装するローカルMixinを作成できます







 const mixin = { created() { // logic ... }} new Vue({ mixins: [mixin],
      
      





さらに、それ(混合?it?..)は再びグローバルになります。







 Vue.mixin({ created() {// logic ... }})
      
      





結局のところ、グローバルミックスインとほぼ同じことを行うプラグインがあります。







 const MyPlugin = { install(Vue, options) { Vue.mixin({ created() { // logic ... }}) }
      
      





もちろん、これらの機能はすべて特定のタスクに実際に必要であり、非常に便利です。

ただし、開発者にとって、特に初心者にとって、どのオプションを選択するかは必ずしも明らかではありません。







必要なコードを確認する



Vuexを使用しているという事実にもかかわらず、私は、州ではなくデータ()を使用しないことは非常に難しい場合があることを自分で指摘しました。







これは速度の問題です。データに何かを追加する方が速いことは明らかですが、ほとんどの場合、データを状態に移動して余分な時間を費やす必要があることがわかります。







おそらく、コードのレビューがなく、Vueをあまり経験していない多数の後輩がいるプロジェクトでは、状況は特に悲しいでしょう。







数ヶ月でこのようなコードを扱うことは完全に不快になると思います。







単体テスト



また、Angularの後、Jestでいくつかのものを濡らすのはあまり便利でも明白でもありませんでした。

具体的な例は、ローカルストレージです。 誰かがこの問題をgithubでグーグル検索することで決定しました







 Object.defineProperty(window, 'localStorage', { value: localStorageMock, })
      
      





解決策は私には美しく見えませんでしたが、後で判明したように、 よりエレガントなものがあります







 global.localStorage = localStorageMock;
      
      





はい、これはVueの問題ではなく、Angularと比較した生態系の問題です。







私の意見では、まさにそのような実際の例はドキュメントに記載されるべきです。







クックブック



一般に、Vueの担当者はこの問題を認識しており、 レシピ付きクックブックを作成することで解決しています

実際、これは一般的なタスクに対する既製のソリューションのセットです。

例は次のとおりです。 単体テスト

検証HTTPの操作







しかし、レシピはまだ非常に基本的であり、深刻なタスクには非常に欠けています。

テストが説明されており、一般的な理解のためにはこれで十分ですが、上記のモッキングを自分で探す必要があります。







検証については後で説明しますが、HTTPの操作については、十分に詳しく説明されていません。







Angularはサービスを通じてバックエンドAPIを操作することを教えてくれたと思いますが、これはコードのサポートと再利用を大幅に促進する良いパターンだと思います。







しかし、私たちには悪名高いDIがなく、サービスインスタンスの作成はあまり便利ではないので、クックブックにも同様のパターンが必要です。







ほとんどの場合、ローカルコードの規則とベストプラクティスを開発することにより、この問題を解決しました。 記事の最後のリンク







TypeScript



TypeScriptがいかに便利で便利であるかについて何度も述べ、書いてきましたが、事実、あなたはそれを調理できる必要があるということです。







Angularでは、すべてが実験的な機能(装飾)、内部クラス、および数百(数千?)の冗長な抽象化に関連付けられています。













Vueでは、TypeScriptの可能な使用法ははるかに論理的です。開発者の機能を拡張できるのは、1つまたは別の言語機能に縛られることなく可能です。







VueのTypeScriptの問題



ただし、今日、VueでTypeScriptを使用するのは必ずしも簡単ではないため、ここでいくつかの問題に遭遇しました。







第一に、彼ら自分の壊れたテスト=(((







もちろん、冗談は私の個人的な痛みです







2つのアプローチ



VueのTypeScriptの主な問題は、 それを使用するための公式のアプローチ2つあることです。







これはVue.extendです(Vueにバンドルされており、メインライブラリと共にサポートされているタップ)







 import Vue from 'vue' const Component = Vue.extend({ ... })
      
      





Angular decorator vue-class-componentに非常に似ています







 import Vue from 'vue' import Component from 'vue-class-component' @Component({ template: '<button @click="onClick">Click!</button>' }) export default class MyComponent extends Vue { message: string = 'Hello!' onClick (): void { window.alert(this.message) } }
      
      





個人的に、私はクラスコンポーネントが好きではありません、そして、多くの理由でVue.extendを使用します:







  1. クラスコンポーネントには独自のトリック/欠点があります
  2. デフォルトのES6 Vueコンポーネントをできる限り避けたい

    • TS用に編集する必要なく、ドキュメントから直接コードを使用します
  3. チームは、TypeScriptなしでVueがどのように機能するかを理解する必要があります。

    • 特に、ほとんどが角度のある背景を持つことを考慮して


その他の問題



悲しみの度合いを変えた、TypeScriptのいくつかの問題を次に示します。







  1. TSlint はそのままでは Vueで動作しません-.vueファイルに対しては実行できません 。 一般に、fork-ts-checkerによる解決策がありますが、それらはすべていです
  2. TypeScriptのESlintは控えめに言ってもスーパーではありません。 プラグインとパーサーの両方がまだ開発中です。

    多くのコアおよびビュールールは破られますが、主な問題は非常に不明瞭なエラーがあることです。

    ただし、これにもかかわらず、壊れたルールを無効にし、必要なルールをひねって具体的に使用します。

    ESlint configへのリンク
  3. Vuexストアは外部で入力されていないため、これを呼び出すthis.$store



    コンポーネントからのthis.$store



    は事実上すべてのペイロードで可能


ただし、Vue.extend()には次のような欠点があります。







  1. クラス(キャプテン)として、プライベート、静的メソッドなどを使用することはできません。
  2. Vuexのマッパーによる痛み... mapGetters()、... mapState()など これらのマッパーを使用すると、入力が失われ、奇妙なエラーが表示されます。 決定が満たされるのを待っています。
  3. データ()プロパティを入力するのは不便です これは関数です-その戻り値を記述するインターフェースを作成する必要があるたびに
  4. 小道具の正直なタイピングは一般的にほとんど不可能です。 ネイティブJS型を宣言する必要があり、通常はTypeScriptインターフェイスが期待されますが、キャストにはい解決策があります


 //      myObjectProps interface MyType = {...} //   data interface MyComponentData = { someBooleanProp: boolean; } export default Vue.extend({ data(): MyComponentData { //    data  return { someBooleanProp: false }; }, props: { myObjectProps: Object as MyType //   TS  },
      
      





Vuexを使用したフォーム



一般に、フォームはVuexの問題だけでなく、ほぼすべての状態管理パターンです。

それでも、それは一方向のデータフローを伴い、形式は双方向の缶詰を意味します。







Vuexは2つのソリューションを提供しています。







value



を状態値にバインドし、更新するために-コミットを送信する入力イベント:







 <input :value="message" @input="updateMessage">
      
      





 // ... computed: { ...mapState({ message: state => state.obj.message }) }, methods: { updateMessage (e) { this.$store.commit('updateMessage', e.target.value) } }
      
      





または、それにもかかわらず、双方向のカヌーとv-model



ゲッターとセッターを介して取得およびコミットします。







 <input v-model="message">
      
      





 // ... computed: { message: { get () { return this.$store.state.obj.message }, set (value) { this.$store.commit('updateMessage', value) } } }
      
      





2番目のオプションはより便利で簡潔ですが、それでも非常に冗長です。

このように20以上のフィールドを持つフォームを記述することを想像してみてください。

このような一見原始的なタスクのための膨大な量のコードが判明しました。







マッパー、つまりmapGetters()



およびmapMutations()



を使用する場合、問題の関連性はやや低くなります。

しかし、上で書いたように、彼らは現在TypeScriptでうまく機能しておらず、別の解決策を探す必要がありました。







ゲッター(状態からのゲッター)とセッター(コミット突然変異)を追加する非常に原始的なマッパーを作成しました。







 static mapTwoWay<T>(getter: string, mutation: string) { return { get(this: Vue): T { return this.$store.getters[getter]; }, set(this: Vue, value: T) { this.$store.commit(mutation, value); } }; }
      
      





これにより、コードの量を減らし、フィールドを次のように記述できます。







 stringTags: Util.mapTwoWay<IDatasetExtra[]>(STRING_TAGS, UPDATE_STRING_TAGS)
      
      





そして、それに応じて、 v-model



使用します。







 v-model="stringTags"
      
      





フォーム検証



Angularの後で私を驚かせたのは、Vueの箱から出してすぐにはフォームの検証がないことです。 どうやら、この機能は非常に人気があります。







ただし、これは重要ではありません。このタスクには2つの最も一般的なソリューションがあります。







vee-validate



1つ目は、Angular- vee-validateのテンプレート駆動フォームに非常によく似たメカニズムです。







実際、すべての検証ロジックをHTMLで記述します。







 <input v-validate="'required|email'">
      
      





このアプローチは、比較的小さい/複雑でないフォームにのみ適していると思います。

実際には、検証は非常に洗練されていることが多く、HTMLですべてを記述することは不便になります。







さらに、Vuexではうまく機能しません。







検証する



2番目の解決策はVuelidateです。 ほとんどすべてのコンポーネントを検証するための非常にエレガントな方法-モデル自体が検証され、1つまたは別の入力ではありません。







おもしろいことに、このすばらしいパッケージを発見する前に、私たちはすでに似たようなものを書き始めていました。







 <input v-model="name" @input="$v.name.$touch()">
      
      





 import { required, email } from 'vuelidate/lib/validators' export default { data () { return { name: '' } }, validations: { name: { required, email } } }
      
      





必要に応じて、フォームの検証でVuelidateをすぐに検討することを強くお勧めします。これは(Vuexを含む)うまく機能し、接続とカスタマイズが簡単です。







Vueメインチップ/問題



実際、これが主な問題です (?)Vue-それは単なるライブラリであり、だまされたオールインワンフレームワークではありません。







箱から出して:









はい、公式にサポートされています:









しかし、これらすべての機能を備えたVueには、Animationのようなクールな組み込み機能があります。







かつて私は、何かをアニメーション化するための最も豊かな可能性に多少驚いていました。







これは、おそらく同じAngularよりもはるかに便利で強力なツールボックスです。







ドキュメントからのクールな例













ナイトウォッチとe2e



やはりVueに直接関係しない小さな問題ですが、実際のプロジェクトで遭遇しました。







e2eテスト用のプロジェクトを生成するとき、すぐにNightwatchCypressのどちらかを選択できます。







個人的には、今日のサイプレスがe2eテストの最もクールなツールであると私は考えていますが、Chrome以外のブラウザはまだサポートされていません







そのため、戦闘プロジェクトには選択できませんでした。実際のカスタムユーザーは引き続き他のブラウザを使用しています。







テストが完全に不可解な理由でLinux CIに該当し始めたら(Windowsではすべて問題ありませんでした)、エラーは有益ではありませんでした。

後で、問題がURLのハッシュ(#)に関連していることがわかりました。

つまり、 vue-router



を使用する場合、そのようなURLはデフォルトです。







, ChromeDriver



, Nightwatch ( Cypress TestCafe), "" url :







 .url('data:,') .url(client.globals.devServerURL + `/#/my-hashed-url`)
      
      









Angular boilerplate , , Vue .







, , Developer Experience. , .







, .









Vue — React Native.

.







, Vue NativeScript Vue, , , .

Weex, , .







性能



. .















: http://www.stefankrause.net/js-frameworks-benchmark7/table.html

( " " ).







: GitLab ,

CodeShip , Alibaba, Xiaomi .







おわりに



.







— TypeScript Vue , , .







, production.

, , TS Vue, JavaScript.







, , , TypeScript .







Vue , , .







, " ", Tide Vue .







code conventions



, , .

, .













cookbook — , ( ).







Vue seed (TS, Jest, ESlint ..), , Vue CLI 3,

.

Vue CLI 3 .







??



はい ご清聴ありがとうございました。

PS: , Vue — ,







PPS: , () — =(







: https://medium.com/@igogrek/how-i-started-loving-vue-d41c1c8e77e1








All Articles