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/n/373213.html