Я объясню различия в совместном использовании данных между API-интерфейсом option и API-интерфейсом композиции. Также продемонстрирую потенциальные способы использования API-интерфейса композиции для обмена данными от дочернего компонента к родительскому компоненту, например испускание и предоставление.
Если вы создаете дочерний компонент с помощью API композиции, свойства и методы этого компонента будут закрытыми. Вы не сможете получить доступ к частным свойствам и методам извне этого компонента.
<script setup> //composition api with setup script // any property or methods are private import { ref } from 'vue' const name= ref("child component"); const increase =()=>{ return count.value = count.value + 1; } </script>
Но если вы создаете компонент с помощью option API, свойства и методы этого дочернего компонента будут общедоступными. Таким образом, родительский компонент может получить доступ к свойствам и методам дочерних компонентов, используя этот экземпляр компонента или цепочки $parent
.
<script> // any property or method are public //accessible from parent export default { data() { return { name: '', } }, methods: { increase() { return this.count = this.count + 1; }, }, } </script>
Существует два способа передачи данных от дочернего компонента к родительскому с помощью API композиции с настройкой сценария.
- defineExpose
- Создать событие
defineExpose:метод defineExpose позволяет компоненту предоставлять свои методы и свойства общедоступным для родительского компонента.
Чтобы обеспечить передачу данных между дочерним компонентом в родительский с использованием API композиции с defineExpose, вам необходимо выполнить два шага.
Шаг 1: используйте метод defineExposeв дочернем компоненте, чтобы предоставить свойства и методы.
defineExpose()
Я сделал имя isAdult и свойства count общедоступными, а также методы увеличения и уменьшения. За исключением свойства age, остальные общедоступны из родительского компонента.
//ChildComponent.vue <script setup> import { ref, defineExpose } from "vue"; const name = ref("child component"); const count = ref(1); const isAdult = ref(false); const age = ref(17); const increase = () => { count.value = count.value + 1; isAdult.value = count.value > age.value; }; const decrease = () => { if (count.value > 0) count.value = count.value - 1; isAdult.value = count.value > age.value; }; //age is private //rest of the properties & methods are public defineExpose({ name, count, isAdult, increase, decrease, }); </script> <template> <h5>Child To Parent Data passing</h5> </template>
Шаг 2. В родительский компонент вам необходимо добавить дочерний компонент. Теперь вам нужно создать экземпляр дочернего компонента.
Используя Template Ref, вы можете создать экземпляр дочернего компонента. Я объяснил Template Ref в своем предыдущем посте. Нажмите, чтобы перейти туда.
Здесь я добавил ChildComponent.vue в родительский компонент. Я также создал экземпляр n с именем child из ChildComponent.vue. Используя этот экземпляр, я получил доступ к общедоступным свойствам name, isAdult и count, а также к методам увеличения и уменьшения.
//ParentComponent.vue <script setup> import ChildComponent from "./ChildComponent.vue"; import { ref, onMounted, computed } from "vue"; const child = ref(null); const childComponetName = ref(""); const onChildIncrement = () => { child.value.increase(); //increase child count }; const onChildDecrement = () => { child.value.decrease(); //decrease child count }; onMounted(() => { childComponetName.value = child.value.name; // child components name is not updating //so i have read it after initial render }); const childComponetCount = computed(() => { return child.value?.count; // if child count update it will return the latest count; }); const isParentsChildAdult = computed(() => { return child.value?.isAdult; // if child isAdult update it will return the latest isAdult; }); </script> <template> <div> <ChildComponent ref="child" /> <p>Count:{{ childComponetCount }}</p> <p>Adult child? {{ isParentsChildAdult }}</p> <div class="btn"> <button type="button" @click="onChildDecrement">decrement</button> <button type="button" @click="onChildIncrement">increment</button> </div> </div> </template> <style scoped> .btn { display: flex; justify-content: center; gap: 20px; } </style>
Emit Event:используяметодmit, вы можете создать собственное событиеt и передавать данные из дочерний элемент родительского компонента/прослушивающего компонента. Всякий раз, когда дочерний компонент запускает событие, прослушивающий/родительский компонент будет прослушивать это событие и действовать соответствующим образом.
Методы Emit принимают уникальное имя события и данные события. Вы можете игнорировать данные о событии, но имя события является обязательным.
emit('customEventName', eventData); or emit('customEventName'); //customEventName must be unique
Чтобы обеспечить передачу данных между дочерним компонентом в родительский с помощью API композиции с emite, вам необходимо выполнить два шага.
Шаг 1:Создайте пользовательское событие с отправкой в дочернем компоненте. Вы можете создавать пользовательские события из шаблона вашего компонента. >или раздел сценария.
Раздел скрипта: если вы используете submit с настройкой скрипта, вы должны объявить пользовательские события непосредственно в defineEmits. Здесь я объявил как handleIncrease, так и handleDecrease. > события в defineEmits. Позже я создал эти события и передал свойства как данные событий.
<script setup> import { defineEmits, ref } from "vue"; //list of declared custom events const emit = defineEmits(["handleIncrease", "handleDecrease"]); const count = ref(1); const age = ref(17); const increase = () => { count.value = count.value + 1; const isAdult = count.value > age.value; emit("handleIncrease", count.value, isAdult); //custom event with event data }; // const decrease = () => { if (count.value > 0) count.value = count.value - 1; const isAdult = count.value > age.value; emit("handleDecrease", count.value, isAdult); //custom event with event data }; </script>
Раздел шаблона. Для встроенного излучения вам не нужно объявлять какие-либо пользовательские события. Вот почему я создал непосредственное встроенное getSearchInputсобытие из шаблонов и передал значение поиска в качестве данных события.
<script setup> import {ref } from "vue"; const search = ref(""); </script> <template> <input type="text" class="form-control" v-model="search" @input="$emit('getSearchInput', search)" /> </template> <style scoped> .form-control { margin: 10px; } </style>
Рассматривая оба случая, завершите код дочернего компонента с помощью Emit:
//ChildComponent.vue <script setup> import { defineEmits, ref } from "vue"; //list of declared custom events const emit = defineEmits(["handleIncrease", "handleDecrease"]); const count = ref(1); const age = ref(17); const search = ref(""); const increase = () => { count.value = count.value + 1; const isAdult = count.value > age.value; emit("handleIncrease", count.value, isAdult); //custom event with event data }; // const decrease = () => { if (count.value > 0) count.value = count.value - 1; const isAdult = count.value > age.value; emit("handleDecrease", count.value, isAdult); //custom event with event data }; </script> <template> <div class="btn"> <button type="button" @click="decrease">decrement</button> <button type="button" @click="increase">increment</button> </div> <!-- Inline emit getSearchInput & searchValue is passing as argument--> <input type="text" class="form-control" v-model="search" @input="$emit('getSearchInput',search)" /> </template> <style scoped> .form-control { margin: 10px; } .btn { display: flex; justify-content: center; gap: 20px; } </style>
Шаг 2. В родительский/прослушивающий компонент вам необходимо добавить дочерний компонент. Теперь вам нужно связать эти пользовательские события в шаблонах Vue.js, используя директиву on или ее сокращенный символ @.
Итак, я добавил ChildComponent.vue в ParentComponent.vue и привязал все три пользовательских события.
//ParentComponent.vue <script setup> import ChildComponent from "./ChildComponent.vue"; import { ref } from "vue"; const parentCount = ref(1); const isParentsChildAdult = ref(false); const increaseParent = (childCount, isAdult) => { parentCount.value = childCount; isParentsChildAdult.value = isAdult; //Whenever in child component user click increase method, //handleIncrease event will listen and act accordingly }; const decreaseParent = (childCount, isAdult) => { parentCount.value = childCount; isParentsChildAdult.value = isAdult; //Whenever in child component user click descrease method, //handleDecrease event will listen and act accordingly }; const showAlert = (value) => { alert(value); //Whenever in child component user fills input , //getSearchInput event will listen }; </script> <template> <p>{{ parentCount }}</p> <p>Adult child? {{ isParentsChildAdult }}</p> <ChildComponent @handleIncrease="increaseParent" @handleDecrease="decreaseParent" @getSearchInput="showAlert" /> </template>
Спасибо, что дочитали до конца. Пожалуйста, подумайте о том, чтобы подписаться на автора и эту публикацию. Посетите Stackademic, чтобы узнать больше о том, как мы демократизируем бесплатное образование в области программирования во всем мире.