最近在使用qiankun框架对vue子应用进行拆分时,出现了此问题:在子应用使用element中的下拉框,会被定位到父应用的顶部,丢失了top的距离,同时控制台报错如下:

报错原因
element中的下拉框是通过appendChild的方式添加到对应的位置,而在使用的时候可能主应用和子应用都使用了element,子应用内下拉框无法准确识别,因此appendChild到了父应用上。
一、解决方法一
首先在【父应用】内若开启了沙箱的strictStyleIsolation,需要关闭,没有就不管

既然是appendChild方法无法识别子应用内,那么就在【子应用内】重写appendChild方法;在项目根文件内(main.js),生成实例render方法中改变append到子应用中。
// 顶部定义一个全局的originFn,最后卸载时需要还原给父应用
let originFn = document.body.appendChild.bind(document.body)
// 实例生成
function render(props = {}) {
console.log('routes ', routes);
const { container } = props;
redirectPopup(container)
const router = initRouter()
// 为了避免根 id #app 与其他的 DOM 冲突,需要限制查找范围
instance = new Vue({
router,
store,
render: h => h(App),
}).$mount(container ? container.querySelector('#app') : '#app');
// 重写子应用的element的appendChild方法 element组件弹出框挂在到子应用内
function redirectPopup(container) {
// 子应用中需要挂载到子应用的弹窗的className,用作标记
const addPopup = 'el-select-dropdown el-popper el-zoom-in-top-leave el-zoom-in-top-leave-active'
const editPopup = 'el-select-dropdown el-popper'
const whiteList = [addPopup, editPopup]
// 保存原有document.body.appendChild方法
let originFn = document.body.appendChild.bind(document.body)
// 重写appendChild方法
document.body.appendChild = (dom) => {
// 根据标记,来区分是否用新的挂载方式
if (whiteList.includes(dom.className)) {
container.querySelector('#app').appendChild(dom)
} else {
originFn(dom)
}
}
}
/**
* 应用每次 切出/卸载 会调用的方法,通常在这里我们会卸载微应用的应用实例
*/
export async function unmount() {
instance.$destroy();
instance.$el.innerHTML = '';
instance = null;
router = null;
document.body.appendChild = originFn; // 卸载时还原append方法
removeRouter()
}
二、解决方法二
如果第一种方法没能解决弹出框的定位问题,element中也给出了一个定位解决方案

每一个下拉框中添加这个属性popper-append-to-body: false; 只是通常我们项目中的下拉框数量比较多,若是一个一个添加就较为麻烦,最好把三方引用作为官方组件
三、解决方法三
github上也有类似的问题,估计是2.10.x版本的都有问题,建议降低版本到2.9.3尝试: https://github.com/umijs/qiankun/issues/2408
2628

被折叠的 条评论
为什么被折叠?



