「翻訳」Vueの反応性システムはあなたが想像していたよりも強いです.


Photo by Bruno Oliveira on Unsplash
原文:https://levelup.gitconnected.com/vue-reactivity-system-is-more-powerful-than-you-think-37b1924d681b
Vue 3の複合APIと改善された反応システムは、Web開発者を笑わせる.本当ですか.
最近私はVUEを大学の課題として使って、アプリケーションの開発からWeb開発者として自由に取引しています.私は今VUEに夢中になっています.
Vueはシンプルで先進的な原則に基づいて、フロントエンドの開発に多くの機能を提供しています.重要な要因は反応システムである.

なぜ反応性が必要なのか。


フロントエンドの開発は非常に簡単です.簡単に言えば、データが動的であれ静的であれ、バックエンドから受信したデータを表示するだけです.残りはインタフェースがスムーズで、ユーザーに安定した使用体験を提供するだけです.少なくとも「使い心地がいい」と一言で十分です.
バニラJavaScriptを使って論理を実現するのもいいですね.ただし、画面上でコールバック、条件、またはイベントの動的データを更新すると、異なる状況が発生します.要するに、簡単なカウンタアプリケーションを作成する場合は、バニラJavaScriptを使用して次の操作を実行できます.
開発で原文で使用されているstackblitz iframeが正常にレンダリングされていないため、リンクとサムネイルに置き換えられます.
  • https://stackblitz.com/edit/simple-counter-vanilla-z4hjbh
  • <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="utf-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1" />
        <script src="https://cdn.tailwindcss.com"></script>
        <title>Simple Counter</title>
      </head>
      <body>
        <div class="w-full mt-8 flex justify-center">
          <span id="counter" class="text-3xl font-bold"></span>
        </div>
        <div class="w-full mt-4 flex flex-row space-x-4 justify-center">
          <button
            id="decrement"
            class="
              text-lg
              font-semibold
              bg-gray-500
              hover:bg-gray-600
              transition
              py-1
              px-4
              text-white
              rounded
              drop-shadow-xl
            "
          >
            -
          </button>
          <button
            id="increment"
            class="
              text-lg
              font-semibold
              bg-gray-500
              hover:bg-gray-600
              transition
              py-1
              px-4
              text-white
              rounded
              drop-shadow-xl
            "
          >
            +
          </button>
        </div>
        <div class="w-full mt-4 flex flex-row space-x-4 justify-center">
          <button
            id="reset"
            class="
              text-md
              font-medium
              bg-red-500
              hover:bg-red-600
              transition
              py-1
              px-4
              text-white
              rounded
              drop-shadow-xl
            "
          >
            Reset
          </button>
        </div>
      </body>
    
      <script type="text/javascript">
        document.addEventListener('DOMContentLoaded', function () {
          const counter = document.querySelector('span#counter');
          const incrementButton = document.querySelector('button#increment');
          const decrementButton = document.querySelector('button#decrement');
          const resetButton = document.querySelector('button#reset');
    
          let count = 0;
    
          if (counter) {
            // set counter initial value
            updateCounter();
    
            // set buttons onclick callback
            incrementButton.onclick = function () {
              count++;
              updateCounter();
            };
            decrementButton.onclick = function () {
              count--;
              updateCounter();
            };
            resetButton.onclick = function () {
              count = 0;
              updateCounter();
            };
          }
    
          function updateCounter() {
            // update the counter view
            counter.innerHTML = count;
          }
        });
      </script>
    </html>
    
    バニラJavaScriptを使用する場合は、ボイラーボードコードが大量に必要です.DOM準備完了を待つ必要があります.DOMコンポーネントをクエリーする必要があります.onclickイベントハンドラを構成し、イベントが発生したときに直接ビューを更新する必要があります.
    そうです.例は簡単すぎるかもしれません.しかし、複雑な特徴と論理を持つ複雑なアプリケーションを想像してみてください.簡単で当たり前のことをするために、努力しすぎたのではないでしょうか.
    次に、VUEを使用してこれらの機能を実装するとどうなるかを見てみましょう.(ViteはTypescriptと併用)
    開発で原文で使用されているstackblitz iframeが正常にレンダリングされていないため、リンクとサムネイルに置き換えられます.
  • https://stackblitz.com/edit/simple-counter-vue-d6hk3v
  • <script setup lang="ts">
    import { ref } from 'vue';
    import PrimaryButton from './PrimaryButton.vue';
    import DangerButton from './DangerButton.vue';
    
    const count = ref(0);
    </script>
    
    <template>
      <div class="w-full mt-8 flex justify-center">
        <span ref="counter" class="text-3xl font-bold">{{ count }}</span>
      </div>
      <div class="w-full mt-4 flex flex-row space-x-4 justify-center">
        <primary-button ref="decrementButton" title="-" @click="count--" />
        <primary-button ref="incrementButton" title="+" @click="count++" />
      </div>
      <div class="w-full mt-4 flex flex-row space-x-4 justify-center">
        <danger-button ref="resetButton" title="Reset" @click="count = 0" />
      </div>
    </template>
    
    なお、上記の例は、VUEのComponentAPIを用いて記述されている.CompositionAPIは、以前のバージョンVueで紹介されたオプションAPIの継承者です.要するに、CompositionAPIは、より堅牢で、より簡単で、コールバックがより少ないAPIを使用してVueコードを記述することを可能にする.これらのAPI間の相違は別の記事で説明される.src/components/Counter.vueから以下のインストーラに、同じカウンタ機能が追加されました.
    <script ... >
      ...
      
      const count = ref(0);
    </script>
    <template>
      ...
      <span>{{ count }}</span>
      <primary-button title="-"     @click="count--" />
      <primary-button title="+"     @click="count++" />
      <danger-button  title="Reset" @click="count = 0" />
    </template>
    ref@clickイベントバインディングとともに使用するだけで、同じタスクを完了できます.残りはVUEの反応系によって処理される.
    簡単だけど面白いそれを知っていますか.refはかっこいいやつだ.あなたは想像以上に強いことをすることができます.src/components/Video.vueファイルを表示します.
    <script ... >  
      ...
      const video = ref<HTMLVideoElement>();
    
      onMounted(async () => {
        await setupVideo(video);
        video.value.play();
      });
      
      async function setupVideo(video: HTMLVideoElement) {
        video.value.width = 640;
        video.value.height = 320;
        video.value.allowfullscreen = true;
        video.value.controls = true;
        video.value.type = "video/webm";
        video.value.src = " ... ";
      }
    </script>
    <template>
      <video ref="video" />
    </template>
    ComponentAPIのrefは、任意の設定を必要とせずに静的タイプのDOM要素にバインドすることができる.refというHTMLタグ名と要素タイプというref変数を宣言するだけです.ほとんどのDOMタイプはHTMLElementを継承しているので、このタイプを使用することができます.
    以前のバージョンのVueは、refを介して要素this.$refsにアクセスすることができる.Vue 3はこの方法を推奨しません.特に、タイプスクリプトを使用している場合は、静的タイピングの問題を回避します.
    まだ終わってないよrefの価値はその価値をはるかに下回っています.しかし、私がもっと難しいことを言う前に、Vueの状態管理について話しましょう.

    ステータスマネージャに連絡してください



    Photo by CartoonNetworkLA on Tenor
    Vue、React、その他のフロントエンドフレームワークを試してみると、ステータス管理という言葉が簡単に聞こえるかもしれません.まだ慣れていない場合は、簡単に説明します.
    技術的には、すべてのVue要素インスタンスがその反応状態を「管理」している.上記の例で説明したように、構成部品インスタンスの状態は、refを使用して管理される.
    構成部品は、次の要素を持つ独立した単位です.
  • 状態は、ドライバアプリケーションのデータ記憶である.
  • viewはステータスの宣言マッピングです.
  • 動作は、ビューにユーザが入力した応答によって状態を変更する方法である.

  • ######「一方向データストリーム」の概念の簡単な概略図
    動作を例の単純なカウンタとして扱うと、ユーザが「インクリメンタル」または「減量」または「リセット」ボタンを押下したときに実行されます.ステータスはcount変数であり、viewはユーザが表示するカウントテキストである.
    これが「ステータス管理」です.
    しかし、同じ状態を持つ複数の構成部品が発生すると、管理状態が難しくなります.
  • の複数のビューは、1つの状態に依存する可能性がある.
  • 異なるビューでの動作は、ステータスセグメントを変更する必要がある場合があります.
  • 反応性APIを使用した状態管理



    Photo by CartoonNetworkLA on Tenor
    アプリケーションがますます大きくなるにつれて、コンポーネントレベルのステータスではなく、グローバルアプリケーションのステータスを管理する必要がある場合があります.これは、各構成部品がアプリケーションのグローバル・ステータスから値を取得したり、グローバル・ステータスを変更したりできることを意味します.
    VUEの反応性APIは、この機能を容易に実施する.複数の構成部品インスタンスで共有する必要がある場合は、refを使用して反作用オブジェクトを作成し、複数の構成部品からインポートして使用できます.
    Vueでこれらの機能を実装するには、storeインスタンスを作成します.
    // store.ts
    import { ref } from 'vue'
    
    export const store = ref({
      count: 0,
      increment() {
        this.count++
      }
    })
    そしてVue素子で使えばいいです
    <!-- ComponentA.vue -->
    <script setup lang="ts">
    import { store } from './store'
    </script>
    
    <template>
      <button @click="store.increment()">
        From A: {{ store.count }}
      </button>
    </template>
    他のVue素子にも使用できます.
    <!-- ComponentB.vue -->
    <script setup lang="ts">
    import { store } from './store'
    </script>
    <template>
      <button @click="store.increment()">
        From B: {{ store.count }}
      </button>
    </template>
    storeがどこで変更されても、<ComponentA><ComponentB>は自動的にviewを更新します.単一のデータ・リポジトリ(single source of truth)が作成されました.これは、入力storeの構成部品が書き込みされている場合、storeオブジェクトのincrement()を呼び出すなどの方法で状態を変更できることを意味する.
    ボタンのクリックハンドルには、store.increment()のようなカッコが付いていることに注意してください.これは構成部品の方法ではないので、適切なthisコンテキストでメソッドを呼び出すにはカッコを使用する必要があります.

    ステータス管理ライブラリ


    単純な場合は、反応性APIのみでステータス管理が可能ですが、大規模な本番アプリケーションでは考慮すべき要素がたくさんあります.
  • チームが協力するより強力な会議.
  • Vue DevToolsに連絡し、
  • 時間軸、コンポーネントナビゲーション、および時間トラベルデバッグに使用します.
  • HMR (Hot Module Replacement).
  • サーバ側レンダリングサポート.

  • Photo by turtlepirate223 on Tenor
    上記の要件を考慮すると、PiniaまたはVuexなどのVueのステータス管理ライブラリを使用できます.
    Piniaは、上記のすべての要件を満たすステータス管理ライブラリです.Vue Coreチームが管理し、Vue 2とVue 3と互換性があります.既存のユーザーは、以前の正式なステータス管理ライブラリVuexを熟知している可能性があります.

    n/a.結論


    簡単な場合、refという反応性APIを使用して、ステータスマネージャを簡単に作成できます.さらに、PiniaやVuexなどのVUEステータス管理ライブラリを使用して、複雑なユーズエンクロージャ、HMR、サーバ側のプレゼンテーションをサポートすることもできます.これは全く問題のない方法です.
    VUEの反応性APIは使いやすくて面白い.しかし、反応性APIについては、まだ多くの話があります.次の文章を書くのが本当に楽しみです.