Menggunakan slot di Vue sebagai contoh cuplikan produk

Ketika bekerja dengan proyek-proyek di mana SSR (Server Side Rendering) tidak digunakan atau tidak mungkin untuk mengimplementasikannya, masalah muncul bahwa beberapa fungsi atau logika ditulis dua kali untuk elemen statis yang mencetak backend dan untuk komponen yang membuat Vue.

Misalnya, kita perlu menerapkan komponen cuplikan produk yang memiliki sejumlah persyaratan:

  • Itu dapat dicetak secara statis dari backend dengan semua informasi yang diperlukan untuk SEO dan logika.
  • Ini dapat digunakan sebagai komponen Vue biasa, melewati parameter melalui v-bind, melampirkan peristiwa klik , dll.
  • Seharusnya menampilkan keadaan saat tombol beli
  • Setelah mengklik tombol "Beli", preloader akan muncul menunggu status keranjang

Satu solusi:

  1. Tulis logika untuk cuplikan statis dengan melampirkan peristiwa klik, menambah dan menghapus kelas muat pada tombol Beli
  2. Secara terpisah, tulis komponen pada Vue yang mengimplementasikan logika yang sama hanya dalam format template
  3. Gunakan item pertama untuk mengeluarkan dari backend, yang kedua, misalnya, untuk mengeluarkan data bersih yang diperoleh dari status atau ajax

Jadi kita akan menulis dua logika, satu akan bekerja secara langsung dengan DOM, yang lain dengan data murni.

Solusi saya untuk masalah ini adalah dengan menggunakan slot, yaitu, kemampuan untuk mengatur konten default, yang akan berisi parameter dinamis, tetapi pada saat yang sama jika komponen digunakan sebagai inline-templat, semua parameter ini akan diganti dengan yang digambar oleh backend.

Mari kita menulis komponen yang dapat menangani statika dan dinamika:

Daftar komponen
<template> <div> <!--   image   ,       --> <slot name="image"> <!--    --> <a :href="url" class="snippet__image"> <img :src="image"> </a> </slot> <slot name="title"> <a :href="url" class="snippet__title">{{ title }}</a> </slot> <div v-if="!inCart" @click="add" :class="{ 'snippet__buy--load': load }" class="snippet__control" > <slot name="button"> <div class="snippet__button"></div> </slot> </div> <div v-if="inCart" class="snippet__control"> <div class="snippet__button"></div> </div> <div v-if="load" class="snippet__load"></div> </div> </template> <script> //  vuex     import { mapState, mapActions } from 'vuex' export default { props: { id: { type: Number, required: true }, url: { type: String }, image: { type: String }, title: { type: String } }, data() { return { //   load: false, //     inCart: false, } }, computed: { ...mapState({ //     cartItems: ({cart}) => cart.items }), }, mounted() { this.$nextTick(() => { //      this.inCart = this.cartItems.some(item => item.id === this.id) }) }, methods: { ...mapActions([ //     'addToCart' ]), add() { //    this.load = true //   this.addToCart({ id: this.id }) } }, watch: { //      cartItems(items) { //    this.load = false //      this.inCart = items.some(item => item.id === this.id) } } } </script> 


Menggunakan komponen melalui backend:

 <snippet :id="1" class="snippet"> <a slot="image" href="#" class="snippet__image"> <img src="photo.jpg"> </a> <a slot="title" href="#" class="snippet__title"> 1</a> <div slot="button" class="snippet__button"></div> </snippet> 

Menggunakan komponen dalam komponen lain:

 <catalog-list> <snippet v-for="item in items" :key="item.id" v-bind="item"></snippet> </catalog-list> 

Sekarang kami memiliki satu komponen yang dapat digunakan dalam berbagai kasus.

Saya ingin mendengar pendapat Anda tentang pendekatan ini, mungkin ada solusi yang lebih baik.

Source: https://habr.com/ru/post/id422465/


All Articles