angualrjs动态加载分析

来源:互联网 发布:linux 查找字符串 编辑:程序博客网 时间:2024/06/05 03:21

作者:胡兵

动态加载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);

上面的定义方法就是你使用module来定义这些方法的背后实现方法,经我实践是切实可行的,结合动态js加载,就可以实现angualrjs的动态加载了。缺点就是你以后定义controller、service、directive需要改变方法了,本质还是一样的,思路更是一样的。
0 0