升级 vue@3.5 时遇到奇怪的问题, 页面点击离开没反应
经过排查, 是以下几点相互作用导致此问题
- vue 有应用上下文的概念, 例如 runWithContext API,
- vue-router 在调用钩子时会获取 vue 的应用上下文
- element-plus 在唤起弹窗时会从 parent 或 应用上下文上拿到 config 信息
- 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>