Untuk komponen pihak ketiga, bagaimana untuk memanjangkan fungsi secara elegan sambil mengekalkan fungsi asal komponen pihak ketiga (prop, acara, slot, kaedah)?
Ambil el-input Element Plus sebagai contoh:
Kemungkinan besar anda pernah bermain seperti ini sebelum ini, merangkum komponen MyInput dan meletakkan prop, acara dan slot yang akan digunakan , tulis kaedah sekali lagi mengikut keperluan anda sendiri:
// MyInput.vue <template> <div class="my-input"> <el-input v-model="inputVal" :clearable="clearable" @clear="clear"> <template #prefix> <slot name="prefix"></slot> </template> <template #suffix> <slot name="suffix"></slot> </template> </el-input> </div> </template> <script setup> import { computed } from 'vue' const props = defineProps({ modelValue: { type: String, default: '' }, clearable: { type: Boolean, default: false } }) const emits = defineEmits(['update:modelValue', 'clear']) const inputVal = computed({ get: () => props.modelValue, set: (val) => { emits('update:modelValue', val) } }) const clear = () => { emits('clear') } </script>
Tetapi selepas tempoh masa, keperluan berubah, dan fungsi lain komponen el-input perlu ditambahkan pada komponen MyInput Komponen el-input mempunyai sejumlah 20 Terdapat berbilang atribut, 5 acara, dan 4 slot Apa yang perlu kita lakukan satu persatu. Ini bukan sahaja menyusahkan tetapi juga mempunyai kebolehbacaan yang lemah.
Dalam Vue2, kami boleh mengendalikannya seperti ini, klik di sini untuk melihat enkapsulasi komponen pihak ketiga Vue
Artikel ini adalah untuk membantu anda memindahkan pengetahuan anda dan meneroka cara menggunakan Vue3 CompositionAPI untuk merangkum komponen pihak ketiga dengan elegan~
dalam Vue2
$attrs: termasuk pengikatan Atribut fungsi induk dalam domain yang tidak diiktiraf (dan diperoleh) sebagai prop (kecuali kelas dan gaya). Apabila komponen tidak mengisytiharkan sebarang prop, semua pengikatan skop induk (kecuali kelas dan gaya) akan disertakan di sini dan komponen dalaman boleh dihantar melalui v-bind="$attrs"
$pendengar: Mengandungi pendengar acara v-on dalam skop induk (tidak termasuk .pengubah suai asli). Ia boleh lulus v-on="$listeners" untuk lulus dalam komponen dalaman
dan dalam Vue3
$attrs: mengandungi induk peranan Pengikatan dan peristiwa atribut (termasuk acara kelas, gaya dan tersuai) yang tidak digunakan sebagai prop komponen atau peristiwa tersuai dalam domain juga boleh dihantar ke komponen dalaman melalui v-bind="$attrs".
Objek $listeners telah dialih keluar dalam Vue 3. Pendengar acara kini menjadi sebahagian daripada $attrs.
Fungsi tambahan useAttrs dalam
//MyInput.vue <template> <div class="my-input"> <el-input v-bind="attrs"></el-input> </div> </template> <script setup> import { useAttrs } from 'vue' const attrs = useAttrs() </script>
Sudah tentu, ini tidak mencukupi. Hanya menulis dengan cara ini, atribut yang kami ikat (termasuk kelas dan gaya) juga akan berkuat kuasa pada elemen akar (contoh di atas ialah nod Dom dengan class="my-input"). Untuk mengelakkan tingkah laku lalai ini, kita perlu menetapkan inheritAttrs kepada false.
Mari kita lihat penjelasan dokumen Vue3 tentang inheritAttrs
Secara lalai, pengikatan atribut dalam skop induk yang tidak dikenali sebagai prop akan "berbalik" dan Digunakan pada elemen akar komponen anak sebagai atribut HTML biasa. Apabila menulis komponen yang membungkus elemen sasaran atau komponen lain, ini mungkin tidak sentiasa mematuhi tingkah laku yang dijangkakan. Dengan menetapkan inheritAttrs kepada false, gelagat lalai ini akan dialih keluar. Atribut-atribut ini boleh dijadikan berkesan melalui instance property $attrs, dan boleh diikat secara eksplisit kepada elemen bukan akar melalui v-bind.
Jadi, kita boleh menulis kod berikut untuk memproses prop dan acara komponen pihak ketiga:
// MyInput.vue <template> <div class="my-input"> <el-input v-bind="attrs"></el-input> </div> </template> <script> export default { name: 'MyInput', inheritAttrs: false } </script> <script setup> import { useAttrs } from 'vue' const attrs = useAttrs() </script>
Vue3
$slots: Kita boleh mendapatkan slot yang diluluskan oleh komponen induk
$scopedSlots telah dialih keluar daripada Vue3, semua Slot terdedah sebagai fungsi melalui $slots
Dalam
Berdasarkan perkara di atas, jika kami tidak menambah slot tambahan untuk pembungkusan komponen pihak ketiga, dan slot komponen pihak ketiga berada dalam nod dom yang sama, kami juga mempunyai kaedah pengkapsulan pintar A ????, dapatkan nama slot dengan merentasi $slot, dan tambah secara dinamik slot subkomponen:
//MyInput.vue <template> <div class="my-input"> <el-input v-bind="attrs"> <template v-for="k in Object.keys(slots)" #[k] :key="k"> <slot :name="k"></slot> </template> </el-input> </div> </template> <script> export default { name: 'MyInput', inheritAttrs: false } </script> <script setup> import { useAttrs, useSlots } from 'vue' const attrs = useAttrs() const slots = useSlots() </script>
Jika syarat di atas tidak dipenuhi, kami harus jujur Tambah slot komponen pihak ketiga yang diperlukan dalam komponen secara manual~
Untuk kaedah komponen pihak ketiga, kami melaksanakannya melalui ref. . Mula-mula, tambahkan atribut ref="elInputRef" pada komponen el-input dalam komponen MyInput, dan kemudian dedahkan elInputRef kepada komponen induk melalui defineExpose.
Komponen kanak-kanak: MyInput.vue
// MyInput.vue <template> <div class="my-input"> <el-input v-bind="attrs" ref="elInputRef"> <template v-for="k in Object.keys(slots)" #[k] :key="k"> <slot :name="k"></slot> </template> </el-input> </div> </template> <script> export default { name: 'MyInput', inheritAttrs: false } </script> <script setup> import { useAttrs, useSlots } from 'vue' const attrs = useAttrs() const slots = useSlots() const elInputRef = ref(null) defineExpose({ elInputRef // <script setup>的组件里的属性默认是关闭的,需通过defineExpose暴露出去才能被调用 }) </script>
Halaman induk: Kod panggilan Index.vue adalah seperti berikut:
// Index.vue <template> <my-input v-model='input' ref="myInput"> <template #prefix>姓名</template> </my-input> </template> <script setup> import MyInput from './components/MyInput.vue' import { ref, onMounted } from 'vue' const input = ref('') const myInput = ref(null) // 组件实例 onMounted(()=> { myInput.value.elInputRef.focus() // 初始化时调用elInputRef实例的focus方法 }) </script>
Atas ialah kandungan terperinci Cara API Komposisi Vue3 merangkum komponen pihak ketiga dengan elegan. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!