2008-04-02
动态加载JS
最近在写portal的时候,遇到了portlet的开发,由于portlet的量很大,所以会产生很多js文件,于是就在想,可不可以把js写到数据库中,然后在运行的时候,按需动态加载,做了一下尝试,发现是可以的.
先给出代码:
从数据库里面读js内容,很简单了,只要将jsDom.text=xRequest.responseText;
换成从数据库中取得的js就可以了
先给出代码:
/**
* www.faceye.com 网络支持系统
* 作者:宋海鹏 ecsun@sohu.com/myecsun@hotmail.com/QQ:82676683
* 说明:javascripts 工具类
*
*/
/**
* 动态加载JS文件
*/
var Faceye = {
version : 1.0,
/**
*简单取得httpRequest
*/
httpRequest : function() {
var xRequest = null;
if (window.XMLHttpRequest) {
xRequest = new XMLHttpRequest();
} else if (window.ActiveXObject) {
xRequest = new ActiveXObject("MsXml2.XmlHttp");
}
return xRequest;
},
/**
*简单的加载文件
*/
load : function(src) {
var headerDom = document.getElementsByTagName('head').item(0);
var jsDom = document.createElement('script');
jsDom.type = 'text/javascript';
jsDom.scr = src;
headerDom.appendChild(jsDom);
},
/**
*通过ajax方式加载js
*/
ajaxLoad : function(src) {
var xRequest = this.httpRequest();
xRequest.open('GET',src,true);
xRequest.send(null);
var headerDom = document.getElementsByTagName('head')
.item(0);
var jsDom = document.createElement('script');
jsDom.type = 'text/javascript';
jsDom.language='javascript';
jsDom.defer=true;
jsDom.text=xRequest.responseText;
headerDom.appendChild(jsDom);
}
};
从数据库里面读js内容,很简单了,只要将jsDom.text=xRequest.responseText;
换成从数据库中取得的js就可以了
评论
xiogxiog
2008-04-18
看有多少数据量 看应付什么应用的 场景不同自然用的方法也不同 对于大多数行业还是数据库的天下 因为要解决的问题不仅仅是速度 还有安全、完整、一致等很多问题, 单单强调某一方面无任何意义, 另外还要说的是 一切还是业务需求打头 技术是第二位的
huangyh
2008-04-06
要缓存和gzip压缩吗,你看看e3.resouce, http://www.javaeye.com/topic/179814
williamy
2008-04-06
很好很动态
这让我明白了为什么回字有4种写法
建议作者对aculo的loader研究一下
那是你的反面教材
可能对你的继续创作有益
这让我明白了为什么回字有4种写法
建议作者对aculo的loader研究一下
那是你的反面教材
可能对你的继续创作有益
microboat
2008-04-05
可以用Ext.Ajax来异步加载js片段,比如说这段js封装了一个模块类module,那么需要调用这个模块的时候就用:
Ext.Ajax.request({
method:'GET',
url: 'modules/a01.js',
scope: this,
success: function(response){
var module = eval(response.responseText);
this[a01] = new module();
}
});
ecsun
2008-04-05
同时看到楼上使用这种方式执行js
window.execScript(xhr.responseText);
我更倾向于事前预留接口来执行js
这样的话,我们的代码就会相对统一些,不知道这样是不否合适?
window.execScript(xhr.responseText);
我更倾向于事前预留接口来执行js
这样的话,我们的代码就会相对统一些,不知道这样是不否合适?
ecsun
2008-04-05
我的主要想法是想把未来在系统做好以后,把需要不断扩展的的js写到数据库中,然后加载的缓存中,在需要这样的功能的js的地方,我们从缓存里面动态的去读取.
整体结构就像,我们在框架中留下调用的接口,然后,我们对接口的具体实现,是在数据库中做的,这样一来,我们可以编写一些标准的组件,比如说window,form,panel等,而当我们需要填充panel的时候,我们就通过预先预留出来的接口,从缓存中加载.
这样的思路最初来源于在项目中对模板的使用,在我们使用velocity或是freemarker的时候,我可以在模板中调用相应的类,当我们的项目部署在线上运行的时候,这个时候,频繁的改动java代码,就需要频繁的去重启服务器,对于web 应用来说,频繁的重启服务器,是相当致命的, 所以,对于核心的功能,我们放在java代码中执行,对于相对简单的功能,我们就放在模板里面执行,这样的话,即使需要改动,也不至于频繁的去重启服务器.
这一点,也是我把js代码放入数据库的一个的初衷.经过摸索,发现这个方法,确实可行,把基本的代码贴出来,大伙讨论一下,当然,dojo的加载方式,我还没有具体去看,只是看到dojo导入包的时候,使用importot.
以下是基础的从数据库动态加载js的代码.
整体结构就像,我们在框架中留下调用的接口,然后,我们对接口的具体实现,是在数据库中做的,这样一来,我们可以编写一些标准的组件,比如说window,form,panel等,而当我们需要填充panel的时候,我们就通过预先预留出来的接口,从缓存中加载.
这样的思路最初来源于在项目中对模板的使用,在我们使用velocity或是freemarker的时候,我可以在模板中调用相应的类,当我们的项目部署在线上运行的时候,这个时候,频繁的改动java代码,就需要频繁的去重启服务器,对于web 应用来说,频繁的重启服务器,是相当致命的, 所以,对于核心的功能,我们放在java代码中执行,对于相对简单的功能,我们就放在模板里面执行,这样的话,即使需要改动,也不至于频繁的去重启服务器.
这一点,也是我把js代码放入数据库的一个的初衷.经过摸索,发现这个方法,确实可行,把基本的代码贴出来,大伙讨论一下,当然,dojo的加载方式,我还没有具体去看,只是看到dojo导入包的时候,使用importot.
以下是基础的从数据库动态加载js的代码.
/**
* 动态加载类
*/
var Faceye = {
version : '1.0',
/**
* 取得xmlHttpRequest
*/
httpRequest : function() {
var xRequest = null;
if (window.XMLHttpRequest) {
xRequest = new XMLHttpRequest();
} else if (window.ActiveXObject) {
xRequest = new ActiveXObject("MsXml2.XmlHttp");
}
return xRequest;
},
open : function(url, params, httpMethod) {
var xRequest = this.httpRequest();
xRequest.open(httpMethod, url, false);
xRequest.send();
return xRequest;
}
};
var ClassLoader = function() {
};
/**
* 根据文件路径进行加载
*/
ClassLoader.prototype.loadFormFileSrc = function(url) {
var xRequest = Faceye.httpRequest();
xRequest.onreadystatechange = function() {
var state = xRequest.readyState;
if (state == 4) {
if (xRequest.status == 200 || xRequest.status == 304) {
var source = xRequest.responseText;
var headerDom = document.getElementsByTagName('head').item(0);
var jsDom = document.createElement('script');
jsDom.type = 'text/javascript';
jsDom.language = 'javascript';
jsDom.defer = true;
jsDom.text = source;
headerDom.appendChild(jsDom);
}
}
};
xRequest.open('GET', url, false);
xRequest.send(null);
};
/**
* 加载javascript源文件代码
*/
ClassLoader.prototype.loadFromSource = function(source) {
var xRequest = Faceye.httpRequest();
xRequest.onreadystatechange = function() {
var state = xRequest.readyState;
if (state == 4) {
if (xRequest.status == 200 || xRequest.status == 304) {
var headerDom = document.getElementsByTagName('head').item(0);
var jsDom = document.createElement('script');
jsDom.type = 'text/javascript';
jsDom.language = 'javascript';
jsDom.defer = true;
jsDom.text = source;
headerDom.appendChild(jsDom);
}
}
};
};
rjzou2006
2008-04-05
我为说两句,dojo加载好我不否定,动态加载JS本来就无形的增加了代码的维护性不是吗?
(对于楼主的说法要将JS URL 存入数据库. 以实现动态加载的效果,对以后JS的扩展,来提供便利)
我否定使用数据库来存取这样的东西.(不光说是性能问题).
对上面说的,不能同步顺序问题.有必要在不是使用DODJ的系统为使用它的容器功能吗?
我认为:
A.动态加载这样的JS不能异步从SERVER上取数据.
B.加载JS少用DB.
C.动态加载JS本来就无形的增加了维护难度了.
D.要实现这样的功能是否有比较好的实现方法呢(共同研究)
END.
(对于楼主的说法要将JS URL 存入数据库. 以实现动态加载的效果,对以后JS的扩展,来提供便利)
我否定使用数据库来存取这样的东西.(不光说是性能问题).
对上面说的,不能同步顺序问题.有必要在不是使用DODJ的系统为使用它的容器功能吗?
我认为:
A.动态加载这样的JS不能异步从SERVER上取数据.
B.加载JS少用DB.
C.动态加载JS本来就无形的增加了维护难度了.
D.要实现这样的功能是否有比较好的实现方法呢(共同研究)
END.
ferreousbox
2008-04-04
对于js的动态加载,其实分成两种情况,一种是有很多js,不想在页面上写很多script头,这样我们就需要使用类似dojo的方式来加载了,另外一种就是在运行的过程中执行加载,在没有运行前这个js是不存在于本地的,只有运行到后才从服务器加载,此时就需要加回调方法,当然,这种情况比较少点,也需要看具体情况做相应的调整了。
shatuo
2008-04-03
我的JS开发经验不足,就接触的来说,dojo的加载处理很好,而且dojo的扩展性很好,可以通过继承覆盖掉,加载JS对象文件貌似浏览器的限制不多吧。
dboylx
2008-04-03
to:yeahoo
有没考虑加载多个有依赖关系的类库怎么办?
有没考虑加载多个有依赖关系的类库怎么办?
yeahoo
2008-04-03
我也为没有必要放入数据库。我写了一个JavaScript的加载函数,用Ajax加载。在刚开始的时候以为用这种方式会导致浏览不再缓存JS文件了,经测试浏览器同样会从缓存中加载,使用中不会影响运行效率。
在主流浏览器上测试通过。这个加载函数在我的项目中运行的很好。
在主流浏览器上测试通过。这个加载函数在我的项目中运行的很好。
var $_JS_LOADED = []; //已载入的JavaScript文件
//动态加载JavaScript文件
function $import(src){
if(!$_JS_LOADED[src]){
try{
var xhr = window.ActiveXObject ? new ActiveXObject("Microsoft.XMLHTTP") : new XMLHttpRequest();
xhr.open("GET", src, false);
xhr.send(null);
if(200 == xhr.status || 0 == xhr.status){
if (window.execScript)
window.execScript(xhr.responseText);
else window.eval.call(window, xhr.responseText);
}
$_JS_LOADED[src] = true;
}catch(e){
alert('系统错误: 加载文件"' + src + '"出错! \r\n[在第 ' + e.lineNumber + ' 行出现 ' + e.message + ' 错误]');
}
}
}
dboylx
2008-04-03
shatuo 写道
dboylx 写道
DOJO,EXT等等 加载原理都是一样的,浏览器的限制。
哪方面的限制,是指XMLttpRequest的限制,还是指容器限制(只能在浏览器中运行)?
DOM,BOM,ECMAScript,CSS,HTML... 规范的限制
南极咔咔
2008-04-03
楼主思路很不错!具体验证下会更好。
shatuo
2008-04-03
dboylx 写道
DOJO,EXT等等 加载原理都是一样的,浏览器的限制。
哪方面的限制,是指XMLttpRequest的限制,还是指容器限制(只能在浏览器中运行)?
dboylx
2008-04-03
DOJO,EXT等等 加载原理都是一样的,浏览器的限制。
shatuo
2008-04-03
dojo的加载很棒,不过需要容器的帮忙。
dboylx
2008-04-03
JSLoader=function (){
var cbArr = new Array();
function execCBs(){
for(var i=0;i<cbArr.length;i++){
if(cbArr[i].cb){
try{
if(typeof(cbArr[i].cb) == "function"){
if(typeof(cbArr[i].scope)!="undefined")
cbArr[i].cb.call(cbArr[i].scope)
else
cbArr[i].cb();
}
}
catch(e){alert('script error!')};
cbArr.splice(i--,1);
}
}
};
return {
//加载后的回调
onReady : function(callBack,d){
cbArr.push({cb : callBack,scope : d});
},
//回调方法的运行
execFcs : function(){
execCBs();
},
Ajax : {
//AJAX实现
}
};
}();
JSLoader.jsCache = {currentLevel:1,levelCounter:1,ready:false};
JSLoader.require=function(fileName){
var inStack = false;
if(JSLoader.jsCache[fileName]){
return;
}else{
var js = new Js(fileName);
JSLoader.jsCache[fileName] = js;
JSLoader.jsCache.ready=false;
var currentLevel = JSLoader.jsCache.levelCounter++;
JSLoader.Ajax.request('GET',fileName,{
success:function(response){
JSLoader.jsCache[fileName].loaded = true;
JSLoader.jsCache[fileName].content = response.responseText;
JSLoader.jsCache[currentLevel] = JSLoader.jsCache[fileName]
executeScript(currentLevel);
},
scope:this
}
);
}
function executeScript(executeLevel){
if(executeLevel == JSLoader.jsCache.currentLevel
&& JSLoader.jsCache[executeLevel].loaded){
executeJs(JSLoader.jsCache[executeLevel])
if(executeLevel == (JSLoader.jsCache.levelCounter - 1))
JSLoader.execFcs();
if(++JSLoader.jsCache.currentLevel < JSLoader.jsCache.levelCounter
&& JSLoader.jsCache[JSLoader.jsCache.currentLevel]
&& JSLoader.jsCache[JSLoader.jsCache.currentLevel].loaded){
executeScript(JSLoader.jsCache.currentLevel);
}
}
};
function executeJs(jsObj){
if(window.executeScript){
window.executeScript(jsObj.content);
}else if(window.execScript){
window.execScript(jsObj.content)
}else{
window.eval(jsObj.content);
}
jsObj.content = null;
jsObj.excuted = true;
jsObj.content = false;
}
function Js(fn){
this.fileName=fn;
this.loaded=false;
this.content=null;
this.excuted=false;
}
}
ecsun
2008-04-03
我的做法是
1,不同游览器加载JS要用不同实现,这是第一步,保障代码强壮性必要条件。
这一点
目前我也是这么做的
2,做一个注册机(维护JS加载队列),任何JS加载都通过统一接口加载并注册。
3,注册机严格控制加载顺序,注册机的主要责能。这块很重要,因为不同的游览器加载的方法不一样,但加载是可以像出来的,但抽像出来的东西只能被考虑为异步,这样就迫使控制加载顺序成为一个小问题,我的做法是定义一个当前加载的LEVEL,每加载完毕一个JS文件LEVEL加一。第一次加载页面时可以同时加载N个JS文件, 另一方面的用途,在用户交互的过程中,又可以动态加载更多的JS。以当前LEVEL为参照点可以有效控制加载顺序,这也是我想出的最简单的办法。算法很简单,用JS语言的动态性可以有效的减少递归调用降低算法时间复杂度。
4,注册机加载完所有的文件,状态置为已加载完毕,保存当前加载LEVEL,并通知监听器。
加载这一块目前我没有好的办法,希望可以看到你的代码.
1,不同游览器加载JS要用不同实现,这是第一步,保障代码强壮性必要条件。
这一点
目前我也是这么做的
2,做一个注册机(维护JS加载队列),任何JS加载都通过统一接口加载并注册。
3,注册机严格控制加载顺序,注册机的主要责能。这块很重要,因为不同的游览器加载的方法不一样,但加载是可以像出来的,但抽像出来的东西只能被考虑为异步,这样就迫使控制加载顺序成为一个小问题,我的做法是定义一个当前加载的LEVEL,每加载完毕一个JS文件LEVEL加一。第一次加载页面时可以同时加载N个JS文件, 另一方面的用途,在用户交互的过程中,又可以动态加载更多的JS。以当前LEVEL为参照点可以有效控制加载顺序,这也是我想出的最简单的办法。算法很简单,用JS语言的动态性可以有效的减少递归调用降低算法时间复杂度。
4,注册机加载完所有的文件,状态置为已加载完毕,保存当前加载LEVEL,并通知监听器。
加载这一块目前我没有好的办法,希望可以看到你的代码.
dboylx
2008-04-03
动态类JS加载,我觉得应用范围不广。
相对独立的,小的,与全局作用域完全无关的才可以用这个方法。但既然您已经写出了一个类库,没有强至的约束(事实是根本无法做)时很容易产生错误。
相对独立的,小的,与全局作用域完全无关的才可以用这个方法。但既然您已经写出了一个类库,没有强至的约束(事实是根本无法做)时很容易产生错误。
dboylx
2008-04-03
我的做法是
1,不同游览器加载JS要用不同实现,这是第一步,保障代码强壮性必要条件。
2,做一个注册机(维护JS加载队列),任何JS加载都通过统一接口加载并注册。
3,注册机严格控制加载顺序,注册机的主要责能。这块很重要,因为不同的游览器加载的方法不一样,但加载是可以像出来的,但抽像出来的东西只能被考虑为异步,这样就迫使控制加载顺序成为一个小问题,我的做法是定义一个当前加载的LEVEL,每加载完毕一个JS文件LEVEL加一。第一次加载页面时可以同时加载N个JS文件, 另一方面的用途,在用户交互的过程中,又可以动态加载更多的JS。以当前LEVEL为参照点可以有效控制加载顺序,这也是我想出的最简单的办法。算法很简单,用JS语言的动态性可以有效的减少递归调用降低算法时间复杂度。
4,注册机加载完所有的文件,状态置为已加载完毕,保存当前加载LEVEL,并通知监听器。
1,不同游览器加载JS要用不同实现,这是第一步,保障代码强壮性必要条件。
2,做一个注册机(维护JS加载队列),任何JS加载都通过统一接口加载并注册。
3,注册机严格控制加载顺序,注册机的主要责能。这块很重要,因为不同的游览器加载的方法不一样,但加载是可以像出来的,但抽像出来的东西只能被考虑为异步,这样就迫使控制加载顺序成为一个小问题,我的做法是定义一个当前加载的LEVEL,每加载完毕一个JS文件LEVEL加一。第一次加载页面时可以同时加载N个JS文件, 另一方面的用途,在用户交互的过程中,又可以动态加载更多的JS。以当前LEVEL为参照点可以有效控制加载顺序,这也是我想出的最简单的办法。算法很简单,用JS语言的动态性可以有效的减少递归调用降低算法时间复杂度。
4,注册机加载完所有的文件,状态置为已加载完毕,保存当前加载LEVEL,并通知监听器。
发表评论
提醒: 该博客已发表在公共论坛,博客所有留言会成为论坛回贴,留言请注意遵守论坛发贴规则
- 浏览: 44141 次
- 性别:


- 详细资料
搜索本博客
我的相册
Faceye基础版(开源)新建标签页
共 24 张
共 24 张
链接
最新评论
-
Faceye基础版(开源)介绍 ...
可以支持其它数据库,数据库无关的,DAO主要为Hibernate,目前已知有朋友 ...
-- by ecsun -
Faceye基础版(开源)介绍 ...
能否支持其他数据库
-- by netwalkerli -
Faceye基础版(开源)介绍 ...
Faceye刚刚起步,还有很多不完善的地方需要进一步完善,可以给大伙带来欢喜,是 ...
-- by ecsun -
Faceye基础版(开源)介绍 ...
谢谢你奉献
-- by lzmhehe -
Faceye基础版(开源)介绍 ...
目前已知已经有很多朋友安装成功了,MySQL数据库导入历来存在编码等一系列问题, ...
-- by ecsun






评论排行榜