ExtJS Modern工具包launch内setMainView设置主视图异常求解
问题原因
Modern工具包与Classic工具包的应用启动时序存在设计差异:Ext.app.Application的launch()方法执行时,Modern工具包的Ext.Viewport实例还未完成DOM挂载与布局初始化,此时直接调用setMainView()会出现两类异常:
- 传入类名字符串时,视图实例会被挂载到临时脱离文档流的容器中,虽能通过组件查询拿到实例,但不会渲染到页面可见区域,表现为白屏
- 传入配置对象时,组件初始化阶段拿不到有效的父容器引用,直接触发布局计算运行时错误
静态配置mainView项之所以正常,是因为框架内部会把静态配置的主视图的初始化逻辑延后到Viewport就绪后执行,属于框架预留的默认时序。
解决方案
以下两种方案均支持登录态校验、权限判断这类动态设置主视图的业务场景,兼容Modern/Classic双工具包:
方案1:监听Viewport就绪事件后设置主视图(推荐)
保留静态mainView配置作为启动占位,等Viewport完成初始化后再调用setMainView()替换成目标视图,完全兼容两种参数传参形式,适配Sencha 6.5+所有版本:
Ext.application({ name: 'Fiddle', launch: function () { const app = this; // 此处编写前置业务逻辑,例如登录态校验、配置拉取、权限判断等 const userHasLogin = Boolean(localStorage.getItem('userToken')); // 等待Viewport挂载完成后再执行主视图设置 Ext.Viewport.once('ready', () => { if (userHasLogin) { // 两种传参方式都可正常运行 app.setMainView('MyApp.view.main.Main'); // 或 app.setMainView({ xtype: 'app-main' }); } else { app.setMainView('MyApp.view.login.Login'); } }); }, // 初始占位视图,不要删除该配置 mainView: { xtype: 'container', html: '<div style="text-align:center;padding-top:40vh">应用加载中...</div>' } });
该写法在Classic工具包下也可正常运行:Classic环境中Viewport的ready事件会在launch执行前就触发,回调会立即执行,不会产生额外加载延迟。初始占位视图可以配置全局加载动画,优化启动体验。
方案2:直接操作Viewport挂载视图(低版本兼容兜底)
针对6.5以下的低版本Modern工具包(无viewportready事件),可以判断当前运行的工具包类型,绕过setMainView方法直接操作Viewport挂载视图:
launch: function () { const app = this; // 前置业务逻辑 const targetViewConfig = userHasLogin ? { xtype: 'app-main' } : { xtype: 'login' }; if (Ext.isModern) { // Modern环境下直接向Viewport添加视图实例 Ext.Viewport.add(Ext.create(targetViewConfig)); } else { // Classic环境走原有逻辑 app.setMainView(targetViewConfig); } }
注意事项
- 不要完全删除静态
mainView配置:如果不设置该配置项,Modern工具包会跳过Viewport初始化的部分核心步骤,后续手动挂载视图也可能出现布局偏移、事件绑定失效等问题 - 动态切换主视图时如果需要销毁旧视图,可在设置新视图前调用
Ext.Viewport.removeAll()清理原有内容,避免内存泄漏
内容的提问来源于stack exchange,提问作者MX Starter
相关产品推荐
相关产品推荐

