Saya berurusan dengan komunikasi antara dua komponen (menggunakan Vue 2), salah satunya ialah butang, yang boleh mempunyai keadaan seperti permulaan, pemuatan dan penyiapan (berjaya atau gagal), untuk setiap keadaan butang saya mungkin memaparkan keadaan yang berbeza teks, ikon berbeza (memuat: ikon putaran, berjaya diselesaikan: tandakan, penyelesaian ralat: x), saya juga mempunyai borang yang akan menggunakan komponen butang. Saya tidak pasti cara menukar keadaan butang berdasarkan keadaan semasa penyerahan borang. Sila lihat kod di bawah.
Komponen butang saya:
<template> <button class="ui-button" @click="clicked" :data-status-type="status_type" :disabled="is_disabled" :type="type" > <i :class="icon" v-if="is_disabled || concluded"></i> {{ title }} </button> </template> <script> export default { props: { title: { type: String, }, type: { default: "button", type: String, }, }, data() { return { concluded: false, icon: "fa fa-spin ", is_disabled: false, status_type: "success", }; }, methods: { clicked() { if (!this.is_disabled) { this.$emit( "clicked", () => { this.is_disabled = true; this.icon = "fa fa-spin fas fa-spinner"; }, (succeeded) => { this.is_disabled = false; this.concluded = true; this.icon = succeeded ? "fas fa-check" : "fas fa-xmark"; this.status_type = succeeded ? "success" : "error"; setTimeout(() => { this.concluded = false; this.icon = ""; this.status_type = ""; }, 1500); } ); } }, }, }; </script>
Komponen borang saya:
<template> <div> <ThePages :parents="accompaniments"> <!-- ... some reactive stuff --> <template #extra_button> <TheButton @clicked="sendItemToCart" :title="button_text" :disabled="button_disabled" /> </template> </ThePages> </div> </template> <script> import axios from 'axios' import FormatHelper from '../helpers/FormatHelper' import SwalHelper from '../helpers/SwalHelper' import TheButton from './TheButton.vue' import ThePages from './ThePages.vue' import TheQuantityPicker from './TheQuantityPicker.vue' export default { props: ['product'], components: { TheButton, ThePages, TheQuantityPicker, }, data() { return { accompaniments: this.product.accompaniment_categories, button_text: '', button_disabled: false, format_helper: FormatHelper.toBRCurrency, observation: '', quantity: 1, success: false, } }, created() { this.addQuantityPropToAccompaniments() this.availability() }, methods: { // ... some other methods async sendItemToCart(startLoading, concludedSuccessfully) { startLoading() // This will change the button state this.button_text = 'Adicionando...' await axios .post(route('cart.add'), { accompaniments: this.buildAccompanimentsArray(), id: this.product.id, quantity: this.quantity, observation: this.observation, }) .then(() => { concludedSuccessfully(true) // This will change the button state this.button_text = 'Adicionado' SwalHelper.productAddedSuccessfully() }) .catch((error) => { concludedSuccessfully(false) // This will change the button state if ( error?.response?.data?.message == 'Este produto atingiu a quantidade máxima para este pedido.' ) { SwalHelper.genericError(error?.response?.data?.message) } else { SwalHelper.genericError() } this.button_text = 'Adicionar ao carrinho' }) }, }, } </script>
Dalam kod di atas, anda boleh melihat cara saya menukar keadaan butang berdasarkan keadaan borang: Butang saya mengeluarkan dua fungsi apabila diklik (startLoading, includedSuccessfully), dan saya kemudian menggunakan kedua-dua fungsi ini dalam sendItemToCart.
Ini nampaknya menggandingkan kedua-dua komponen itu terlalu banyak, kerana saya perlu menghantar fungsi ini sebagai parameter kepada kaedah komponen induk. Selain itu, saya mempunyai idea lain tentang cara melakukan ini, iaitu memberi setiap butang rujukan dan kemudian memanggil kaedahnya menggunakan ref dalam komponen induk. Idea ini berbunyi sedikit seperti "komposisi dan bukannya warisan" dalam pengaturcaraan berorientasikan objek, di mana saya hanya meminta objek/komponen untuk melakukan sesuatu, tetapi dalam kes ini, tanpa mengambil fungsi sebagai parameter.
Nah, kedua-dua kes di atas kelihatan lebih baik daripada mencipta pembolehubah untuk setiap butang yang mungkin saya miliki, tetapi ia kelihatan seperti ia boleh diperbaiki. Jadi apa yang saya cari ialah: Bagaimanakah saya boleh memisahkan komponen saya dengan lebih baik?
Jika kita bercakap tentang Vue 3 (anda tidak menyatakan versi Vue, jadi tidak pasti ia Vue 2), anda mungkin sedang mencari
provide/inject
:https://vuejs.org/guide/components/provide-inject.html
Jadi, jika anda mempunyai komponen induk dan sekumpulan komponen anak yang hanya boleh muncul sebagai keturunan komponen induk (seperti borang dan kotak input), anda boleh
provide
nyatakan borang:OP mengulas bahawa butang mungkin muncul di tempat lain juga, jadi kita harus menggunakan kedua-dua prop dan menyediakan. Jika tiada borang, kita boleh menggunakan prop sebagai nilai suntikan lalai.
Dalam komponen bentuk:
Dalam komponen butang:
Laraskan kod pada API Pilihan.
Dikemas kini dengan Vue 2
OP membetulkan jawapan, menggunakan Vue 2. Jadi...
Nasib baik, Vue 2 juga menyokongnya
provide/inject
! Satu-satunya masalah ialah bagaimana untuk membuat menyediakan responsif, yang saya rasa diselesaikan di sini:Bagaimana cara saya menjadikan Vue 2 Provide / Inject API reaktif?