Vue.js untuk pemula pelajaran 9: acara khusus

Dalam pelajaran sebelumnya di kursus Vue kami, Anda telah mempelajari cara membuat komponen dan cara meneruskan data dari entitas induk ke anak-anak menggunakan mekanisme props. Bagaimana jika data perlu ditransfer ke arah yang berlawanan? Hari ini, dalam pelajaran kesembilan, Anda akan belajar bagaimana membangun komunikasi dua arah antara komponen dari tingkat yang berbeda.







β†’ Vue.js pemula pelajaran 1: contoh Vue

β†’ Vue.js untuk pemula, pelajaran 2: mengikat atribut

β†’ Vue.js pemula pelajaran 3: rendering bersyarat

β†’ Vue.js pemula pelajaran 4: daftar rendering

β†’ Vue .js untuk pemula pelajaran 5: pemrosesan acara

β†’ Vue.js pemula pelajaran 6: mengikat kelas dan gaya

β†’ Vue.js pemula pelajaran 7: properti yang dihitung

β†’ Pelajaran pemula Vue.js 8: komponen

β†’ Vue. js untuk pemula pelajaran 9: acara khusus



Tujuan pelajaran



Kami ingin komponen productdapat memberi tahu entitas induk, instance root Vue, bahwa suatu peristiwa telah terjadi. Dalam hal ini, itu productharus mengirim, bersama dengan pemberitahuan terjadinya peristiwa tersebut, beberapa data.



Kode awal



File index.htmlproyek contoh sekarang berisi kode berikut:



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


Berikut isi file tersebut main.js:



Vue.component('product', {
  props: {
    premium: {
      type: Boolean,
      required: true
    }
  },
  template: `
  <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>
  `,
  data() {
    return {
      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;
      },
      shipping() {
        if (this.premium) {
          return "Free";
        } else {
          return 2.99
        }
      }
    }
})

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


Tugas



Sekarang productini disajikan sebagai komponen mandiri, producttidak masuk akal bahwa kode yang terkait dengan keranjang ada di dalamnya. Jika setiap produk memiliki keranjangnya sendiri yang perlu kita pantau statusnya, aplikasi kita akan menjadi sangat berantakan. Sebaliknya, kami ingin gerobak berada di root instance Vue. Kita juga membutuhkan komponen untuk productmemberi tahu root Vue tentang menambahkan item ke keranjang, yaitu tentang klik pada tombol Add to cart.



Keputusan



Mari pindahkan data yang terkait dengan gerobak kembali ke root Vue instance:



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


Selanjutnya, mari kita pindahkan template keranjang kembali ke index.html, membawa kodenya ke formulir ini:



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

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


Sekarang, jika Anda membuka halaman aplikasi di browser dan mengklik tombol Add to cart, tidak ada yang terjadi seperti yang diharapkan.





Mengklik tombol Add to cart belum menghasilkan apa-apa



. Apa yang akan terjadi jika tombol ini diklik? Kami membutuhkan bahwa saat mengkliknya, instance root Vue akan menerima pemberitahuan yang akan memanggil metode yang memperbarui keranjang, yaitu memperbarui nilai yang disimpan di dalamnyacart.



Untuk mencapai ini, pertama-tama mari kita tulis ulang kode metodeaddToCartkomponenproduct.



Sekarang terlihat seperti ini:



addToCart() {
  this.cart += 1;
},


Mari kita bawa ke formulir ini:



addToCart() {
  this.$emit('add-to-cart');
},


Apa maksud semua ini?



Jadi begitulah adanya. Saat metode dipanggil addToCart, peristiwa bernama kustom dibuat add-to-cart. Dengan kata lain, ketika tombol Add to cartdiklik, sebuah metode dipanggil yang menghasilkan peristiwa yang menunjukkan bahwa tombol baru saja ditekan (yaitu, peristiwa yang dipicu oleh klik tombol baru saja terjadi).



Tapi sekarang, tidak ada di aplikasi yang menunggu acara ini, tidak mendengarkannya. Mari tambahkan pendengar acara ke index.html:



<product :premium="premium" @add-to-cart="updateCart"></product>


Di sini kami menggunakan konstruksi tampilan @add-to-carddengan cara yang sama seperti kami menggunakan konstruksi :premium. Tetapi jika itu :premiumadalah "pipa" yang melaluinya data dapat dikirim ke komponen anak dari induk, maka @add-to-cartitu dapat dibandingkan dengan "penerima radio" dari komponen induk, yang menerima informasi dari komponen anak bahwa tombol telah ditekan Add to cart. Karena "radio" berada dalam tag yang <product>bersarang <div id="app">, ini berarti bahwa ketika informasi tentang sebuah klik tiba , Add to cartmetode yang updateCartterletak di instance root Vue akan dipanggil . Diterjemahkan ke dalam bahasa biasa,



kodenya @add-to-cart=Β«updateCartΒ»terlihat seperti ini: "Ketika Anda mendengar bahwa suatu peristiwa telah terjadi add-to-cart, panggil metode tersebut updateCart."



Metode ini, yang sekarang akan dideklarasikan di objek opsi yang digunakan saat membuat instance Vue, Anda mungkin pernah melihat di suatu tempat:



methods: {
  updateCart() {
    this.cart += 1;
  }
}


Faktanya, ini adalah metode yang persis sama yang digunakan sebelumnya product. Tapi sekarang ini dalam instance root Vue dan dipanggil dengan klik tombol Add to cart.





Tombol berfungsi kembali



Ketika Anda mengklik tombol yang terletak di sebuah komponenproduct, sebuah metode dipanggiladdToCartyang menghasilkan sebuah peristiwa. Instance root Vue, mendengarkan radio, mempelajari bahwa peristiwa telah terjadi dan memanggil metodeupdateCartyang menambah jumlah yang disimpan di dalamnyacart.



Kami telah mencapai tujuan kami, tetapi dalam aplikasi nyata, mengetahui bahwa suatu peristiwa telah terjadi, bahwa produk tertentu telah ditambahkan ke keranjang, tidak akan membawa banyak manfaat. Pada kenyataannya, Anda setidaknya perlu mengetahui produk mana yang telah ditambahkan ke keranjang. Artinya, jika terjadi saat merespons penekanan tombol, Anda juga perlu mentransfer beberapa data.



Data yang diteruskan dalam acara tersebut dapat dideskripsikan sebagai argumen kedua yang diteruskan$emitdalam kode metodeaddToCartkomponenproduct:



this.$emit('add-to-cart', this.variants[this.selectedVariant].variantId);


Sekarang peristiwa tersebut melewati pengenal ( variantId) produk yang ingin ditambahkan pengguna ke keranjang. Artinya, alih-alih hanya menambah jumlah item di troli, kami dapat melangkah lebih jauh dan menyimpan informasi yang lebih detail tentang item yang ditambahkan ke keranjang. Untuk melakukan ini, pertama-tama kita mengonversi gerobak menjadi larik dengan menulis larik kosong ke cart:



cart: []


Selanjutnya, mari kita tulis ulang metodenya updateCart. Pertama - sekarang akan menerima id- pengenal produk yang sama yang sekarang diteruskan dalam acara, dan kedua - sekarang akan menempatkan apa yang diterimanya ke dalam sebuah larik:



methods: {
  updateCart(id) {
    this.cart.push(id);
  }
}


Setelah satu klik pada tombol, pengenal produk ditambahkan ke larik. Array ditampilkan di halaman.





Larik dengan ID produk ditampilkan di halaman.



Kita tidak perlu menampilkan seluruh array di halaman. Kami puas dengan output dari jumlah produk yang ditambahkan ke keranjang, yaitu ke arraycart. Karenanya, kita dapat menulis ulang kode tag<p>, yang menampilkan informasi tentang jumlah produk yang ditambahkan ke keranjang, seperti ini:



<p>Cart({{ cart.length }})</p>




Halaman tersebut menampilkan informasi tentang jumlah item yang ditambahkan ke cart.



Sekarang kita cukup menampilkan panjang array di halaman, atau dengan kata lain, jumlah item yang ada di cart. Secara eksternal, keranjang terlihat sama seperti sebelumnya, tetapi sekarang, alih-alih hanya meningkatkan nilai properti numerikcart, kami menyimpan dalam larikcartinformasi tentang item tertentu yang ditambahkan ke keranjang.



Bengkel



Tambahkan tombol ke proyek yang menghapus cartproduk yang ditambahkan di sana sebelumnya dari larik . Dengan mengklik tombol ini, sebuah acara harus dihasilkan yang berisi informasi tentang pengidentifikasi produk yang akan dihapus dari gerobak.



  • Berikut adalah template yang dapat Anda gunakan untuk mengatasi masalah ini.
  • Inilah solusi untuk masalah tersebut.


Hasil



Inilah yang Anda pelajari hari ini:



  • Sebuah komponen dapat menginformasikan entitas induk bahwa sesuatu telah terjadi di dalamnya menggunakan konstruk $emit.
  • Komponen induk bisa menggunakan penangan kejadian yang ditentukan menggunakan direktif v-on(atau versi singkatannya @) untuk mengatur respons ke kejadian yang dihasilkan oleh komponen anak. Jika suatu peristiwa terjadi, pengendali peristiwa dapat dipanggil di komponen induk.
  • , , .


Jika Anda sedang mempelajari kursus ini dan telah mencapai pelajaran ini, harap beri tahu kami tentang tujuan yang Anda lakukan, apa yang ingin Anda capai dengan menguasai Vue.



β†’ Vue.js pemula pelajaran 1: contoh Vue

β†’ Vue.js untuk pemula, pelajaran 2: mengikat atribut

β†’ Vue.js pemula pelajaran 3: rendering bersyarat

β†’ Vue.js pemula pelajaran 4: daftar rendering

β†’ Vue .js untuk pemula pelajaran 5: pemrosesan acara

β†’ Pelajaran pemula Vue.js 6: mengikat kelas dan gaya

β†’ Pelajaran pemula Vue.js 7: properti terhitung

β†’ Pelajaran pemula Vue.js 8: komponen

β†’ Vue. js untuk pemula pelajaran 9: acara khusus






All Articles