作者:胡兵
动态加载js和css是很容易的,在head中插入script或者link标签就可以办到
function loadjscssfile(filename,filetype,loadfun){
if(filetype == "js"){
var fileref = document.createElement('script');
fileref.setAttribute("type","text/javascript");
fileref.setAttribute("src",filename);
}else if(filetype == "css"){
var fileref = document.createElement('link');
fileref.setAttribute("rel","stylesheet");
fileref.setAttribute("type","text/css");
fileref.setAttribute("href",filename);
}
if(typeof fileref != "undefined"){
fileref.onload = function () {
if(loadfun){loadfun();}
};
document.getElementsByTagName("head")[0].appendChild(fileref);
}
}
// loadjscssfile("do.js","js",function(){});
// loadjscssfile("test.css","css",function(){});
angularjs启动后,再加载的js,js代码可以执行,但js里面按常规方法定义的module,以及定义在该module上的controller、service、directive、filter等无法生效,原因是这些module无法被加载。也就是说需要一次性把所有的js全部加载才能正常工作。
ngInclude的原理:将html文件(也就是模板文件)作为一种资源,通过xhr请求下来,将内容作为dom元素插入父dom元素中,然后使用$compile服务,编译连接后就能正常工作了,前提是html里面引用的controller、service、directive等必须先定义好了,引用的样式也一样需要先定义好,这也就解释了为什么我们需要先通过requirejs把所有的js全部加载了,并且在还把所有的css文件全部也加载了
ngRoute以及angular-ui-router和ngInclude的原理大致相同,如uiView这个指令会根据当前是什么state,然后去加载对应的模板文件,一样的需要编译连接dom元素
我们基于cordova+ionic框架的应用,如果在启动时候加载所有的js,就会在一些性能不好的android手机上面启动时候慢,闪屏等,不是很好的体验;另外我们也有将一个模块打成zip包,下载到客户端,再解压缩使用的需求,如果按以前的方式,需要重定向才能正常工作,重定向就会重新加载,加载慢的问题又会显现出来。
我们想做到的是,我需要哪个模块就加载那个模块的js、css、html,如果那个模块已经加载过就不需要再加载了;这就是后加载技术,也就是动态加载技术。
angularjs动态加载方法,那么传统定义module、controller、service等方法不适用了;需要说明一下的是无论你定义多少module,所有module里面定义的service都统一放在一个实例注入器里面的,所有controller也是放在一处的;因angularjs没暴露模块加载方法,模块加载函数是一个内部方法,外部无法访问,只有在启动创建注入器才内部调用,一个app也只能有一个注入器。因此不再定义module了,命名空间仅限于controller、service、directive的工厂函数,不像我们以前还有有requirejs、module共三层命名空间;动态定义controller、service、directive、filter的方法如下:
- 定义控制器
$controllerProvider.register(name, constructor);
- 定义服务
$provide.provider(name, provider);
$provide.factory(name, $getFn);
$provide.service(name, constructor);
$provide.value(name, value);
$provide.constant(name, value);
$provide.decorator(name, decorator);
- 定义filter
$filterProvider.register(name, constructor);
- 定义directive
$compileProvider.directive(name, directiveFactory);