vue-router钩子中调用ElMessage等样式出错

发布于:2024-10-16 ⋅ 阅读:(5) ⋅ 点赞:(0)

升级 vue@3.5 时遇到奇怪的问题, 页面点击离开没反应
经过排查, 是以下几点相互作用导致此问题

  1. vue 有应用上下文的概念, 例如 runWithContext API,
  2. vue-router 在调用钩子时会获取 vue 的应用上下文
  3. element-plus 在唤起弹窗时会从 parent 或 应用上下文上拿到 config 信息
  4. element-plus 使用了 namespace 功能, 样式表里的类名会从 el-xxx 变为 custom-xxxx

在 vue-router 的钩子里唤起 element-plus 弹窗的行为在 vue@3.4 和 vue@3.5 中出现不同结果
一个能正常获取到 config, 一个获取不到使用了默认值, 由于默认config 创建出来的 dom 没有对应的样式表, 页面上感觉就是没反应了
在这里插入图片描述

复现环境:

// package.json
"element-plus": "^2.8.3",
"vue": "^3.5.8",
"vue-router": "^4.4.5",
复现代码
// 全局引入 element-plus 样式
@forward 'element-plus/theme-chalk/src/mixins/config.scss' with (
  $namespace: 'custom-el'
);
@use 'element-plus/theme-chalk/src/index.scss' as *;

在这里插入图片描述
请添加图片描述

解决方案:

注册 el-config-provider 后, 手动获取到 config 的provide 信息, 注册到应用上下文中

<template>
  <el-config-provider ref="appElConfigProviders" v-bind="config">
    <router-view />
  </el-config-provider>
</template>

<script setup lang="ts">
defineOptions({
  name: 'App'
})

import {
  namespaceContextKey,
  emptyValuesContextKey,
  localeContextKey,
  zIndexContextKey,
  SIZE_INJECTION_KEY
} from 'element-plus'

const config = {
  namespace: 'bms-el',
  emptyValues: ['', undefined, null],
  valueOnClear: null
}

const appElConfigProviders = useTemplateRef('appElConfigProviders')

onMounted(() => {
  const provides = unref(appElConfigProviders)?.$?.provides
  const instance = getCurrentInstance()
  const app = instance?.appContext.app
  if (app && provides) {
    const keys = [
      namespaceContextKey,
      emptyValuesContextKey,
      localeContextKey,
      zIndexContextKey,
      SIZE_INJECTION_KEY
    ]
    keys.forEach(key => {
      provides[key] && app.provide(key, provides[key])
    })
  }
})
</script>