最近自己在搭建一个ExtJs的前端框架,遇到第一个最棘手的问题就是loader了。
注意,这里是ComponentLoader,作用是远程请求一个页面。而不是Ext.Loader,这个是用于动态加载依赖的。
在解决问题期间,百度、google了很多关于loader的信息感觉都不是特别有用,这里我把遇到的问题记录下来供大家参考
首先我选用的Ext5.0.0的版本,应该算是比较新的版本了
1.关于普通的ComponentLoader不执行script的问题
var panel = Ext.create(‘Ext.panel.Panel‘, { loader: { url: url, scripts: true, autoLoad: true, loadMask: true } });
依照API提供的Demo,我们很容易会写出以上的代码,但是在我开发过程中,即使配置scripts:true,也无法执行url页面里的js,使用了很多方法也无法解决这个问题。
最后我重写了控件的render方法并搭配使用了控件的update方法,才勉强达到了和scripts:true相同的效果。
代码如下:
var ctn = Ext.create(‘Ext.container.Container‘, { id: id, title: title, closable: closable == null ? true : closable, layout: ‘border‘, loader: { listeners: { exception: function () { Ext.MessageBox.alert("提示", "页面加载出现异常,请联系管理员") } }, renderer: function (loader, response, active) { var text = response.responseText; loader.getTarget().update(text, true); return true; }, callback: function(loader, success, response, options){ }, url: url, scripts: true, autoLoad: true, loadMask: true } });
如代码所示,在render里将请求返回的html通过update方法的第二个参数true来执行js,并且渲染到目标控件,即ctn里。
注意,这里的update相当于将一段可执行的html执行后,插入目标控件的子项中,这就是为什么我这里要选用container而不选用panel的原因,因为panel会生成panel和panel-body两个div,所以会影响update的执行,使得远程请求的html与panel-body同级,造成html不可见的问题。
以上代码段仅供那些远程请求页面而script不执行的开发人员替代使用,如果scripts可以自动执行,当然不需要多此一举了,其实我不明白这是不是5.0的bug,但是我换成4.2貌似也有这个问题,有高手可以解答我这个疑惑那倒是极好的~~
2.远程请求页面布局问题
我们都知道到,loader一般用来做菜单和tab的联动,ctn是一个远程请求的容器,ctn的父控件就是tabpanel-child,这个我想大家都能明白。但是,不管ctn如何布局,远程请求过来的panel都无法根据ctn的layout自动布局。
ctn的代码在上面已经贴过了,以下是请求页面panel的代码
var page = Ext.create(‘Ext.panel.Panel‘, { region: ‘center‘, layout: { type: ‘table‘, columns: 2 }, items:[gridPanel1,gridPanel2] renderTo: parentId });
是一段很简单的代码,ctn的布局是border,按理来说page应该自动扩展占满父控件的宽高,可事实却没有。update方法执行了远程页面的脚本之后,通过renderTo把page渲染到ctn上,事实是这样做会产生布局问题。
由于ctn先被add到tabpanel中了,update虽然先于add执行,但是确实异步请求,当response时再去渲染,已经无法正确布局了,我也尝试过updateLayout等,好像都不奏效
最后,在史总的帮助下,我多加了一句add语句,而把renderTo去掉,代码改成
var page = Ext.create(‘Ext.panel.Panel‘, { region: ‘center‘, layout: { type: ‘table‘, columns: 2 }, items:[gridPanel1,gridPanel2] }); Ext.getCmp(parentId).add(page);
在代码执行到远程子页面的最后部分时,动态的add这个子页面的panel,我猜想应该是在add源码中执行的重新布局或是其他方面的功能,所以解决了这个布局问题
我原以为update就是add的功能,事实上却不是,虽然观察html元素会发现,虽然元素树节点都是一样的。但是通过class不同我就可以猜测,add里确实执行了重新布局的功能。
只有加了这最后一句,才能把父容器和远程的子页面关联起来,是重中之重。