【Vue3】defineExpose

defineExpose 是 Vue 3.2 引入的一个新 API,它是 <script setup> 的配套 API 之一。在 <script setup> 中,所有定义的变量和函数默认是私有的,不能从组件外部访问。如果你想让外部组件访问到 <script setup> 内定义的属性或方法,你需要使用 defineExpose 显式地暴露它们。

这是 defineExpose 的基本用法:

<script setup>
import { defineExpose } from 'vue'

// ... 定义响应式数据、函数等

defineExpose({
  a,
  b,
  c()
  // ... 这里列出你想暴露的属性和方法
})
</script>

在上面的代码中,a、b 和 c 是在 <script setup> 中定义的,通过 defineExpose 将它们暴露给父组件。这样,父组件就可以通过模板引用(ref)或者 setup() 函数的 context.expose 属性来访问这些暴露的属性和方法。

defineExpose 的引入是为了提供一种清晰的方式来控制组件的公共接口,避免所有的内部状态都被外部访问,从而增强组件的封装性。

完整实例代码

<script lang="ts" setup>
import { computed, onMounted, ref } from 'vue'
import { useAppStore } from '../store/app'
import { useUserStore } from '../store/user'
import GlobalSetup from './global/GlobalSetup.vue'
import GlobalContent from './global/GlobalContent.vue'
import GlobalBreadcrumb from './global/GlobalBreadcrumb.vue'
import GlobalTab from './global/GlobalTab.vue'
import GlobalMenu from './global/GlobalMenu.vue'
import GlobalMainMenu from './global/GlobalMainMenu.vue'
import GlobalMessageTab from './global/GlobalMessageTab.vue'
import { useRouter } from 'vue-router'
import { useMenu } from './composable/useMenu'
import zh_CN from '../lang/zh_CN'
import en_US from '../lang/en_US'

const appStore = useAppStore()
const userInfoStore = useUserStore()
const fullscreenRef = ref()
const visible = ref(false)
const sideWidth = computed(() =>
  appStore.collapse
    ? '60px'
    : appStore.subfield && appStore.subfieldPosition == 'side'
      ? '280px'
      : '220px'
)
const router = useRouter()

const {
  selectedKey,
  openKeys,
  menus,
  mainMenus,
  mainSelectedKey,
  changeMainSelectedKey,
  changeSelectedKey,
  changeOpenKeys
} = useMenu()

onMounted(() => {
  if (document.body.clientWidth < 768) {
    appStore.collapse = true
  }
  userInfoStore.loadMenus()
  userInfoStore.loadPermissions()
})

const changeVisible = () => {
  visible.value = !visible.value
}

const currentIndex = ref('1')

const collapse = () => {
  appStore.collapse = !appStore.collapse
}

const refresh = () => {
  appStore.routerAlive = false
  setTimeout(() => {
    appStore.routerAlive = true
  }, 500)
}

const logOut = () => {
  userInfoStore.token = ''
  userInfoStore.userInfo = {}
  router.push('/login')
}

const locales = [
  { name: 'zh_CN', locale: zh_CN, merge: true },
  { name: 'en_US', locale: en_US, merge: true }
]

const toUserInfo = () => {
  router.push('/enrollee/profile')
}

const toSystemSet = () => {
  router.push('/system/menu')
}

const flag = ref(false)
const changeDropdown = () => {
  flag.value = !flag.value
}

// DefineExpose is needed to expose local variables to parent components
defineExpose({
  sideWidth,
  mainSelectedKey,
  fullscreenRef,
  appStore,
  visible,
  menus,
  mainMenus,
  userInfoStore,
  currentIndex,
  selectedKey,
  openKeys,
  collapse,
  changeOpenKeys,
  changeSelectedKey,
  changeMainSelectedKey,
  changeVisible,
  refresh,
  logOut,
  locales,
  toUserInfo,
  toSystemSet,
  changeDropdown,
  flag
})
</script>

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐