初心者向けVue.jsレッスン8:コンポーネント

今日、Vueコースの8番目のレッスンでは、コンポーネントに初めて触れることになります。コンポーネントは再利用可能なコードブロックであり、アプリケーションの一部のルックアンドフィールとプロジェクト機能の実装の両方を含めることができます。これらは、プログラマーが保守しやすいモジュラーコードベースを作成するのに役立ちます。初心者向けVue.jsレッスン1:Vueインスタンス初心者向けVue.js、レッスン2:属性バインディング初心者向けVue.js、レッスン3:条件付きレンダリング初心者向けVue.js、レッスン4:レンダリングリストVue初心者向けの.js、レッスン5:イベント処理初心者向けのVue.js、レッスン6:クラスとスタイルのバインド



















初心者向けVue.jsレッスン7:計算されたプロパティ

初心者向けVue.jsレッスン8:コンポーネント



レッスンの目的



このレッスンの主な目標は、最初のコンポーネントを作成し、データをコンポーネントに渡すためのメカニズムを調べることです。



初期コード



開始index.htmlするタグに あるファイルコードは次の<body>とおりです。



<div id="app">
  <div class="product">
    <div class="product-image">
      <img :src="image" />
    </div>

    <div class="product-info">
      <h1>{{ title }}</h1>
      <p v-if="inStock">In stock</p>
      <p v-else>Out of Stock</p>
      <p>Shipping: {{ shipping }}</p>

      <ul>
        <li v-for="detail in details">{{ detail }}</li>
      </ul>
      <div
        class="color-box"
        v-for="(variant, index) in variants"
        :key="variant.variantId"
        :style="{ backgroundColor: variant.variantColor }"
        @mouseover="updateProduct(index)"
      ></div>

      <button
        v-on:click="addToCart"
        :disabled="!inStock"
        :class="{ disabledButton: !inStock }"
      >
        Add to cart
      </button>

      <div class="cart">
        <p>Cart({{ cart }})</p>
      </div>
    </div>
  </div>
</div>


コードはmain.js次のとおりです



var app = new Vue({
  el: '#app',
  data: {
    product: 'Socks',
    brand: 'Vue Mastery',
    selectedVariant: 0,
    details: ['80% cotton', '20% polyester', 'Gender-neutral'],
    variants: [
      {
        variantId: 2234,
        variantColor: 'green',
        variantImage: './assets/vmSocks-green.jpg',
        variantQuantity: 10
      },
      {
        variantId: 2235,
        variantColor: 'blue',
        variantImage: './assets/vmSocks-blue.jpg',
        variantQuantity: 0
      }
    ],
    cart: 0,
  },
  methods: {
    addToCart() {
      this.cart += 1;
    },
    updateProduct(index) {
      this.selectedVariant = index;
      console.log(index);
    }
  },
  computed: {
    title() {
      return this.brand + ' ' + this.product;
    },
    image() {
      return this.variants[this.selectedVariant].variantImage;
    },
    inStock(){
      return this.variants[this.selectedVariant].variantQuantity;
    }
  }
})


仕事



Vueアプリケーションのすべてのデータ、メソッド、計算されたプロパティをルートVueインスタンスに配置する必要はありません。時間が経つにつれて、これは保守が非常に困難になるコードにつながります。代わりに、コードをモジュール化された部分に分割して、操作が簡単になり、開発がより柔軟になるようにします。



問題の解決策



まず、既存のコードを新しいコンポーネントに移動することから始めましょう。



これは、main.jsコンポーネントがファイルに登録される方法です



Vue.component('product', {})


最初の引数は、選択したコンポーネント名です。2つ目は、前のチュートリアルでVueをインスタンス化するために使用したものと同様のオプションオブジェクトです。



Vueインスタンスでは、プロパティを使用elしてDOM要素へのバインディングを整理しました。コンポーネントの場合、コンポーネントtemplateのHTMLコードを定義するプロパティが使用されます。



オプションを使用して、オブジェクトのコンポーネントテンプレートを説明しましょう。



Vue.component('product', {
  template: `
    <div class="product">
… //    HTML-,        product
    </div>
  `
})


Vueでテンプレートを作成する方法はいくつかあります。現在、テンプレートリテラルを使用しており、その内容は後引用符で囲まれています。



テンプレートコードが<div>クラスを持つ要素などの単一のルート要素に配置されないことが判明した場合product、次のエラーメッセージが表示されます。



Component template should contain exactly one root element


つまり、コンポーネントテンプレートは1つの要素のみを返すことができます。



たとえば、次のテンプレートは1つの要素のみで表されるため、整形式です。



Vue.component('product', {
  template: `<h1>I'm a single element!</h1>`
})


ただし、テンプレートに複数の兄弟が含まれている場合は機能しません。悪いパターンの例を次に示します。



Vue.component('product', {
  template: `
    <h1>I'm a single element!</h1>
    <h2>Not anymore</h2>
    `
})


その結果、テンプレートに多くの要素、たとえば<div>クラスproductに含まれる要素のセットを含める必要がある場合、これらの要素は外部コンテナ要素に配置する必要があることがわかります。その結果、テンプレートにはルート要素が1つだけ含まれます。



テンプレートに、以前はファイルにあったHTMLコードが含まれているので、index.html以前はルートVueインスタンスにあったコンポーネントにデータ、メソッド、計算されたプロパティを追加できます。



Vue.component('product', {
  template: `
  <div class="product">
…
  </div>
  `,
  data() {
    return {
      //   
    }
  },
    methods: {
      //   
    },
    computed: {
      //    
    }
})


ご覧のとおり、このコンポーネントの構造は、以前に使用したVueインスタンスの構造とほぼ同じです。dataこれがプロパティではなく、オプションを持つオブジェクトのメソッドになっていることに気づきましたか?なぜそうなのですか?



重要なのは、コンポーネントは、それらを再利用する計画で作成されることが多いということです。多くのコンポーネントがある場合はproduct、各コンポーネントに独自のエンティティインスタンスがあることを確認する必要がありますdata。これdataはデータを含むオブジェクトを返す関数になっているため、各コンポーネントは独自のデータセットを受け取ることが保証されています。エンティティがdata関数でなかった場合、各コンポーネントproduct、そのようなコンポーネントが使用された場合は常に、同じデータが含まれます。これは、再利用可能なコンポーネントの考えに反します。



製品関連のコードをネイティブコンポーネントproduct移動したので、ルートVueインスタンスを記述するためのコードは次のようになります。



var app = new Vue({
  el: '#app'
})


ここで、コンポーネントproductをファイルコードに配置する必要がありますindex.html次のようになります。



<div id="app">
  <product></product>
</div>


ここでアプリケーションページをリロードすると、前のフォームに戻ります。





アプリケーションページ



Vue開発者ツールを調べると、ルートエンティティと製品コンポーネントがあることがわかります。





Vue Developer Toolsを使用したアプリケーションの分析



ここで、コンポーネントの再利用性を示すために、コードにindex.htmlさらにいくつかのコンポーネントを追加ましょうproduct実際、これがコンポーネントの再利用の編成方法です。コードindex.htmlは次のようになります。



<div id="app">
  <product></product>
  <product></product>
  <product></product>
</div>


そして、ページには製品カードの3つのコピーが表示されます。





1ページに複数の製品カードが表示される



将来的には1つのコンポーネントproduct作業するため、コードindex.htmlは次のようになります。



<div id="app">
  <product></product>
</div>


仕事



多くの場合、アプリケーションは、親エンティティからデータ、入力パラメータを受け入れるためのコンポーネントを必要とします。この場合、コンポーネントの親はproductルートVueインスタンス自体です。



ルートVueインスタンスにいくつかのデータの説明を持たせます。このデータは、ユーザーがプレミアムアカウントの所有者であるかどうかを示します。 Vueインスタンスを記述するためのコードは次のようになります。



var app = new Vue({
  el: '#app',
  data: {
    premium: true
  }
})


プレミアムユーザーが送料無料の資格があることを決定しましょう。



これはproductpremiumルートVueインスタンスプロパティに書き込まれる内容に応じて、コンポーネントが異なる送料情報出力することを意味しますルートVueインスタンス



プロパティに保存されているデータをpremiumコンポーネントであるに送信するにはどうすればよいproductですか?



問題の解決策



Vueでは、親エンティティから子にデータを転送propsするために、コンポーネントによって記述されたオプションを持つオブジェクトプロパティが使用されます。これは、コンポーネントの入力パラメーターを記述するオブジェクトであり、その値は、親エンティティから受信したデータに基づいて設定する必要があります。



コンポーネントが受け取ると予想される入力パラメータの種類を説明することから始めましょうproduct。これを行うには、オブジェクトの作成時に使用されるオプションを使用して、対応するプロパティをオブジェクトに追加します。



Vue.component('product', {
  props: {
    premium: {
      type: Boolean,
      required: true
    }
  },
  //    , ,  
})


これは、Vueの組み込み機能を使用して、コンポーネントに渡されたパラメーターを検証することに注意してください。つまり、我々は、入力パラメータの種類は何を示しpremiumているBooleanと、このパラメータが設定することによって、必要とされるものrequiredtrue



次に、オブジェクトに渡されたパラメーターを表示するテンプレートに変更を加えましょう。premiumページにプロパティ値表示することで、調査しているメカニズムが正しく機能していることを確認します。



<p>User is premium: {{ premium }}</p>


これまでのところ、すべてが順調に進んでいます。コンポーネントproductは、操作に必要なtypeパラメーターを受け取ることを認識していますBoolean関連データを表示する場所を用意しました。



ただし、パラメータはまだpremiumコンポーネントに渡されていませんこれは、入力パラメーター、特にを送信できるコンポーネントにつながる「行」に類似したカスタム属性を使用して行うことができますpremium



のコードを変更しましょうindex.html



<div id="app">
  <product :premium="premium"></product>
</div>


ページを更新しましょう。





コンポーネントに渡されたデータの出力



入力パラメーターがコンポーネントに渡されるようになりました。私たちが今やったことについて正確に話しましょう。



コンポーネントに入力パラメータ、つまり「カスタム属性」を渡しますpremium。コロン構造を使用してこのカスタム属性を、premiumVueインスタンスデータに格納されているプロパティにバインドします。



これで、ルートVueインスタンスをpremium子コンポーネントに渡すことができますproduct。属性はpremiumVueインスタンスデータのプロパティにバインドされているため、現在の値premiumは常にコンポーネントに渡されますproduct



上の図、つまり碑文はUser is premium: true、すべてが正しく行われたことを証明しています。



これで、調査中のデータ転送メカニズムが期待どおりに機能していることを確認しました。Vue開発者ツールを調べると、コンポーネントに値を格納Productする入力パラメーターがあるpremiumことがわかりますtrue





コンポーネントの入力パラメータ



ユーザーがプレミアムアカウントを持っているかどうかに関するデータがコンポーネントに入力されたので、このデータを使用して、ページに送料情報を表示しましょう。パラメータがpremiumtrue設定されている場合、ユーザーは送料無料の資格があることを忘れないでください新しい計算プロパティshipping作成し、その中でパラメータを使用してみましょうpremium



shipping() {
  if (this.premium) {
    return "Free";
  } else {
    return 2.99
  }
}


パラメータthis.premium格納されている場合true、計算されたプロパティshippingはを返しFreeます。それ以外の場合はを返し2.99ます。



コンポーネントテンプレートからパラメータ値の出力コードを削除しましょうpremium。これで、<p>Shipping: {{ shipping }}</p>今日開始したコードに存在していた要素が、送料に関する情報を表示できるようになります。





プレミアムユーザーは、コンポーネントが値に設定された入力パラメーターを送信されるため、ページに無料配信



テキストShipping: Freeが表示されpremiumますtrue



素晴らしい!これで、親エンティティから子にデータを転送する方法を学習し、コンポーネントでこのデータを使用して商品の配送コストを管理できるようになりました。



ちなみに、子コンポーネントの入力パラメータは変更しないでください。



ワークショップ



product-details入力パラメータdetailsを使用し、次のコードを使用して以前に形成された製品カードの一部のレンダリングを担当 する新しいコンポーネント作成します



<ul>
  <li v-for="detail in details">{{ detail }}</li>
</ul>


これは、この問題を解決するために使用できるテンプレートです。



これが問題解決策です。



結果



今日は、Vueコンポーネントの最初の紹介でした。これがあなたが学んだことです:



  • コンポーネントは、カスタム要素として表示されるコードのブロックです。
  • コンポーネントは、アプリケーションを再利用可能な部分に分割することにより、アプリケーションの管理を容易にします。これらには、アプリケーションの対応する部分のビジュアルコンポーネントと機能の説明が含まれています。
  • コンポーネントデータはdata()、オプション付きオブジェクトのメソッドによって表されます。
  • 入力パラメータ(propsは、親エンティティから子エンティティにデータを渡すために使用されます。
  • コンポーネントが取る入力パラメータの要件を説明できます。
  • .
  • .
  • Vue .




Vue開発者ツールを使用していますか?



初心者向けVue.jsレッスン1:Vueインスタンス

初心者向けVue.js、レッスン2:属性バインディング

初心者向けVue.js、レッスン3:条件付きレンダリング

初心者向けVue.js、レッスン4:レンダリングリスト

Vue .js初心者向けレッスン5:イベント処理

Vue.js初心者向けレッスン6:クラスとスタイルのバインド

Vue.js初心者向けレッスン7:計算されたプロパティ

Vue.js初心者向けレッスン8:コンポーネント






All Articles