我印象中,js脚本文件的loader似乎有,但是完美的,完美到像php的include或者cSharp的using的,貌似没有。有些团队据说有,但是没有一个公认的好的方式,或者说没有一个团队愿意拿出来共享,我觉得这说明,他们的方法都存在问题:或者代码冗余,或者存在n多不确定性,或者只适用于他们自己的环境。

注意我说的是一个文件的loader,是通过script标记的src属性调用,而不是将js代码通过innerHTML写到一个div或者什么标签里。

为什么要写loader呢?

比如jq的冗长是我们经常诟病的一个问题。我在冒死写我自己的类库的一开始,我就确定了一个事情:分文件写。也就是,一个核心的、公共的类库是必需的,然后根据页面需要挂所需的js文件。我觉得这个出发点还是不错的。但是后来我意识到,比如在ui部分,tab标签、无缝滚动、图片轮显、ajax等等诸多部分分在不同的文件中,而往往首页里这些都要用得到,那么,script标记在页头最多时有10个上下。当然,如果你不在意还行。我觉得有点蠢。

jq的冗长是我不要的,script标记过多也不是我要的,所以,我需要一个loader。

但是我还没想好。

这里只做一个简单的实现,实现通过js添加一个script标记,并且确保这个标记引入的文件会被执行。

想到的方式有两种:通过dom添加和通过document.write直接写。

通过dom方式是最方便、简单,并且标准的方式。只要通过document.createElement创建一个script标记,并且按照html标准添加type和src属性,然后把这个标记添加到页面当中去就可以了。但是如我们所知,如果我们不把具体的js代码放到window.onload当中去的时候,js标记的位置是个很重要的问题。也就是说,你的类库文件必须在前,实例应用必须在其后,不但js是逐行的,ie中html也tmd的是逐行的。在添加js标记时,我选择将标记放到head中。并且,head是一个默认标记,就像document,无论你的html中是否有head代码,head标记都是存在的。所以无需判断head标记是否存在,直接用head.appendChild即可。需要注意的问题有二:1、head的获取,在ie下是需要使用getElementsByTagName(‘head’)[0]来获得,其他浏览器直接document.head即可得到。2、执行顺序ie有所不同。我的感觉:在ie下,ie会重新理解标记位置,按script标记在head中的顺序逐行执行引入的文件;而其他浏览器,是按照引入的时间来执行的,比较复合人类的思路。

通过document.write方式,更直接。我先说一下我最终没有采用dom方式的原因:文件加载完成的时间不确定。我幻想过,当我添加了一个新的script标记后,window.onload事件会再次触发一次。当然事实并不是这样。换句话说,我不知道js文件什么时候能够加载完。而当你document.write的时候,所写入的代码会成为html解析的一部分,所以浏览器会等待js文件加载完成以后再执行下面的解析。需要注意的问题:如果在script标记A中使用document.write写了一个script标记B,那么,标记B会紧跟在标记A之后,也就是说是在标记A的外部。所以,在标记A中不能使用动态写入的标记B中的代码,需要在标记A之外重新写script标记来执行标记B中的代码。

最后附上muselite库里暂时新加的window.using代码,这段代码还没有想好怎么用,仅仅完成了文章开头所说的,动态添加的功能而已。

	window.MUSELITE_DEFAULT_FOLDER = 'Scripts';
	(function(w, arr){
		w._using = function(app){
			if(!app || typeof app != 'string') return;
			var i = 0, len = arr.length;
			for(; i < len; i++) arr[i] === null ? document.write(app) : document.write(arr[i]);
		}
		w.using = function(){
			if(arguments.length < 1) return;
			var i = 0, len = arguments.length;
			for(; i < len; i++){
				w._using(arguments[i]);
			}
		}
	})(window, ['']);

*注意匿名函数执行时的第二个参数,实际为

['<scr', 'ipt type="text/javascript" src="', window.MUSELITE_DEFAULT_FOLDER, '/', null, '.js"></scr', 'ipt>']

被wp的编辑器吃掉了