Vue 3在開發過程中引入了新的API `defineExpose`。在以前的版本中,我們經常使用 `$attrs` 和` $listeners` 實現父組件與子組件之間的通信,但是這種做法存在很多弊端,例如,它們只能用於父子組件之間的通信、只能訪問父組件實例上的屬性或方法、難以在slot作用域中繼承等等。現在,使用 `defineExpose` 你可以輕鬆地將值暴露給自己的組件外部,而不必藉助其他API。
一、什麼是defineExpose
在Vue中,組件API分為兩類,一類是外部API,如Vue.component、directives、mixins、props、inject等,他們允許父組件對子組件產生影響。另一類是內部API,例如`$emit`、`$attrs`、`$listeners`等,它們允許子組件對父組件產生影響。而 defineExpose 就是用來將子組件的內部API,變成外部API。
通過 `defineExpose`,子組件將自己的一些內部狀態或方法暴露給父級,達到和$emit相同的效果。
二、defineExpose的使用方法
定義一個子組件:
import { defineComponent, ref, defineExpose } from 'vue'
export default defineComponent({
setup() {
const count = ref(0)
const increment = () => {
count.value++
}
defineExpose({
count,
increment
})
return {
count,
increment
}
}
})
在這個組件中,我們定義了一個計數器的變數和一個`increment`方法,並通過 `defineExpose` 將這些內容暴露出去。
然後在父組件中,我們可以通過`$refs`引用子組件,直接訪問子組件的屬性和方法:
import { ref } from 'vue'
import ChildComponent from '@/components/ChildComponent.vue'
export default {
setup() {
const childRef = ref(null)
const handleClick = () => {
console.log(childRef.count)
childRef.increment()
}
return {
childRef,
handleClick
}
},
components: {
ChildComponent
}
}
在父組件中,我們通過 `components` 屬性註冊了子組件,在 setup 函數中定義了一個 `childRef` 引用,並且通過 `handleClick` 方法來訪問子組件中的 `count` 屬性和 `increment` 方法。
三、defineExpose為多個組件間的通信帶來的便利
除了簡化父子組件之間的通信之外,`defineExpose`還可以為多個組件之間的通信帶來便利。假設我們有兩個組件:`Menu` 和 `MenuItem`。 `Menu` 組件作為容器,包含若干個 `MenuItem` 組件,每個 `MenuItem` 組件有一個選項名稱和一個選項的狀態。我們希望父組件可以直接操作每個菜單項的選項狀態。
首先,我們給 MenuItem 組件添加一個 selected 屬性,並且在 setup 函數中定義一個 toggle 方法,當使用者點擊菜單項的時候,會切換 selected 屬性的值。
import { defineComponent, ref, defineExpose } from 'vue'
export default defineComponent({
props: {
label: {
type: String,
required: true
},
defaultSelected: {
type: Boolean,
default: false
}
},
setup(props) {
const selected = ref(props.defaultSelected)
const toggle = () => {
selected.value = !selected.value
}
defineExpose({
selected,
toggle
})
return {
selected,
toggle
}
}
})
然後在 Menu 組件中,我們可以使用`$refs`引用所有的 MenuItem 項,並暴露 `selected` 屬性和 `toggle` 方法。
import { ref, defineComponent } from 'vue'
import MenuItem from './MenuItem.vue'
export default defineComponent({
components: {
MenuItem,
},
setup() {
const items = ref([])
const toggleAll = () => {
items.value.forEach(item => {
item.toggle()
})
}
return {
items,
toggleAll
}
},
mounted() {
this.items = this.$refs.menuItems.map(item => item)
},
defineExpose({
items: items,
toggleAll: toggleAll
})
})
最後在 Menu 組件的父組件或者其他組件中,我們就可以使用 `$refs` 引用 Menu 組件,並且可以直接訪問到 `toggleAll` 方法和每個菜單項的 `selected` 屬性。
選項
原創文章,作者:GUVNF,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/373213.html