javascript动态加载实现方法一


Posted in Javascript onAugust 22, 2012

现在也有很多JS动态加载的框架,比如In.js。但是这种并不是我想要的编写方式,我来说说我的想法。

先来一段java代码

import Biz.User; 
User u = new User(); 
u.show();

按流程就是导包、实例化、调用。

JS是做不了导包的,或者说代码意义上的导包,一般只是在页面上进行script标签的引入。
那么 先假设需要写成这样

Using("User"); 
var u = new User(); 
u.show();

那么,在JS里面可以实现吗?

来一句一句的分析,当然,前提是页面并不用script标签载入user.js,不然就没意义了。

第一句

Using("User");

为什么用Using,当然只是我的一个命名想法而已,可以联想一下C#,用的就是using,借来而已。

Using里面写入的当然是我需要的对象User,顾名思义,我当然写成Using("User")了。先不说内里是怎么实现的,起码思路是这样。
因为不能模拟关键字写成 Using User;这种起码我是做不到了。
第二句和第三句

var u = new User(); 
u.show();

很正常,就是很平常的实例化与函数调用,唯一不解的是User对象哪里来的?那么当然是第一句导包的时候导入的。

流程就是这么个流程,那么到底能不能实现,关键就在第一句话。也就是说,到底能不能导包成功,而且该怎么导包。

从script标签吸引灵感,对,异步加载所需要的js文件。
也就是说

Using("User");

相当于写了一句
<script type="text/javascript" src="user.js"></script>

现在这么看下来,这么做有意义吗?就为把script标签写成JS动态引入的?或者,只为少写几个字符?

当然不能,这么做毫无意义!那要怎么做?
先从效率来讲。
如果一个页面需要载入N多js文件的时候,如下

<script type="text/javascript" src="jquery.min.js"></script> 
<script type="text/javascript" src="view.js"></script> 
<script type="text/javascript" src="register.js"></script> 
<script type="text/javascript" src="validate.js"></script> 
<script type="text/javascript" src="user.js"></script> 
<script type="text/javascript" src="order.js"></script> 
<script type="text/javascript" src="type.js"></script>

等等等等。

是不是很吓人,那是相当吓人,而且后期维护需要很高的成本,有多少页面,可能就需要修改几个页面。那么,当页面只引入关键的几个js文件,其他文件都采用动态载入的方式呢?
比如我们只需要载入jquery文件,然后调用

$.getScript("user.js",function(){});

这样,我们就做到页面文件里面只需要引入
<script type="text/javascript" src="jquery.min.js"></script>

即可。
那么这种写法的坏处在哪里?看一段代码
$.getScript("user.js",function(){ 
$.getScript("order.js",function(){ 
$.getScript("type.js",function(){ 
$.getScript("validate.js",function(){ 
// and so on.. 
}); 
}); 
}); 
});

PS:用In.js的watch函数是可以避免这种情况产生的。这不在本博文的考虑范围了。

花眼吗?还愿意去对齐代码吗?即便有格式化工具,你还愿意将闭合括号与哪个$.getScript对应吗?当然不愿意。
那么,仿java的导包形式应声而出。

Using("User"); 
Using("Order"); 
Using("Type"); 
Using("Validate"); 
// and so on..

或者你愿意,你可以
Using("User","Type","Order","Validate",...);

写法问题 无所谓。当然我推荐使用第一种方法,清晰。

导包之后,所有的用法不需要任何嵌套,正常使用。

var u = new User(); 
var o = new Order(); 
// and so on..

但是会提出一个问题。假如异步的加载都在Using("XXX")的时候执行,那么
Using("User"); 
Using("Order"); 
Using("Type"); 
Using("Validate"); 
// and so on..

这一段我就需要异步载入4个文件,虽然是异步的,但是未免有些麻烦?而且需要创建4个链接。你愿意合并JS的话,也可以。而且,Using的时候我是不需要使用对象的,这个时候未免太浪费资源了?

至于这个问题,我的解决办法就是学习hibernate,延迟加载,按需加载。
那么怎么做呢?

Using("User");

这个时候肯定是不加载,不加载做什么?当然是返回一个mock,也就是模拟对象。给用户先用着,只有当用户真正需要使用这个对象的时候,再去加载所需的js。也就是说
Using("User"); // 这句话执行完毕之后会创建一个User对象,当时仅仅是个mock 
var u = new User(); // 这个时候用需要的是真实的User对象实例,就在这个时候去动态加载JS文件,并且返回已经实例化的User对象

大家都知道,异步加载是与当前运行的状态不冲突的,也就是说
var u = new User();

这句话执行之后,u是一个没有实际意义值的变量,而已。那么,怎么解决这个问题,我暂且想到的办法,只能是采用同步策略了。只有当js加载完毕,再去执行之后的js语句,这个地方有点遗憾,而且同步可能带来的浏览器假死,也是一个比较严重的问题,暂且不顾这些问题,希望以后能有更好的办法解决。

那问题出来了,这么做同步,有什么优势吗?
我不知道有什么优势,起码对比异步加载,应该没有劣势。比如正常的异步加载为

$.getScript("user.js",function(){ 
var u = new User(); 
});

单单执行这个语句,要执行到function,本质上也是等user.js加载完毕才会执行,那么对比
var u = new User();

理论上时间应该相当,因为都是等user.js加载完毕之后才执行的。

起码第二种看起来更像java式的代码,不必理会其他非业务相关的代码。

那么,怎么会知道需要的对象在什么地方,怎么加载进来?我能想到的就是模拟一个配置文件,为什么用配置文件,而不是像In.js用add函数或者其他框架的类似于register的函数,大概我只是想用配置文件,更像java,而且后期的修改起来也会更解耦一些吧。

Using.Config = { 
"User" : "/js/user" // 可以隐去.js 因为肯定是加载JS文件了 
}

整个思路大概就是这个样子,我在其基础上进行了一些约束,比如加入了命名空间
var u = new Using.Modules.User();

这样可以减少一些全局变量,而且有需要的话,可以插入一些所有对象可能都具有的共性,减少创建类时的重复编码。

当然,也还是支持不使用命名空间的。

为了解决这个约束的效力,加入了Class.create函数来进行类创建约束。

Using.Class.create("User",function(){ 
}).property({ 
}).static({ 
}).namespace(Using.Modules);

这里的大概意思就是

create(类名,构造函数)
property(类的属性)
static(类的静态属性)
namespace(命名空间)

引申到此,为何不加入MVC形式?
后来我发现,要MVC,那么几个类之间的动态维护,或者创建之时就由Using这个类来自动维护,暂时还没想到好的解决办法,所以没有加入其中,只能自己创建类,自己维护了.

通过上面的文字,最后得到一个Using.js
然后在页面里面就只需要引入一个

<script type="text/javascript" src="using.js"></script>

这样接下来就可以写
Using("jquery"); 
Using("User"); $("#ID").click(function(){ 
var user = new User(); 
user.name = "xx"; 
user.show(); 
});
Javascript 相关文章推荐
JavaScript定时器详解及实例
Aug 01 Javascript
探讨JavaScript标签位置的存放与功能有无关系
Jan 15 Javascript
jQuery通过写入cookie实现更换网页背景的方法
Apr 15 Javascript
Jquery Easyui对话框组件Dialog使用详解(14)
Dec 19 Javascript
一个例子轻松学会Vue.js
Jan 02 Javascript
原生JS与jQuery编写简单选项卡
Oct 30 jQuery
vue element-ui 绑定@keyup事件无效的解决方法
Mar 09 Javascript
postman+json+springmvc测试批量添加实例
Mar 31 Javascript
使用vue-cli4.0快速搭建一个项目的方法步骤
Dec 04 Javascript
JavaScript中while循环的基础使用教程
Aug 11 Javascript
vue3.0自定义指令(drectives)知识点总结
Dec 27 Vue.js
js实现碰撞检测
Jan 29 Javascript
原生js写的放大镜效果
Aug 22 #Javascript
window.open不被拦截的实现代码
Aug 22 #Javascript
EASYUI TREEGRID异步加载数据实现方法
Aug 22 #Javascript
网页打开自动最大化的js代码
Aug 22 #Javascript
精心挑选的12款优秀的基于jQuery的手风琴效果插件和教程
Aug 22 #Javascript
eval的两组性能测试数据
Aug 17 #Javascript
javascript五图轮播切换实用版
Aug 17 #Javascript
You might like
PHP Pear 安装及使用
2009/03/19 PHP
php数组的概述及分类与声明代码演示
2013/02/26 PHP
PHP中使用sleep造成mysql读取失败的案例和解决方法
2014/08/21 PHP
php下foreach提示Warning:Invalid argument supplied for foreach()的解决方法
2014/11/11 PHP
PHP实现返回JSON和XML的类分享
2015/01/28 PHP
php使用Header函数,PHP_AUTH_PW和PHP_AUTH_USER做用户验证
2016/05/04 PHP
Laravel如何使用数据库事务及捕获事务失败后的异常详解
2017/10/23 PHP
django中的ajax组件教程详解
2018/10/18 PHP
php中错误处理操作实例分析
2019/08/23 PHP
thinkphp5.1 框架钩子和行为用法实例分析
2020/05/25 PHP
网站导致浏览器崩溃的原因总结(多款浏览器) 推荐
2010/04/15 Javascript
Javascript学习笔记 delete运算符
2011/09/13 Javascript
用jquery和json从后台获得数据集的代码
2011/11/07 Javascript
jQuery循环滚动展示代码 可应用到文字和图片上
2012/05/11 Javascript
Javascript中的关键字和保留字整理
2014/10/16 Javascript
IE中鼠标经过option触发mouseout的解决方法
2015/01/29 Javascript
JavaScript将base64图片转换成formData并通过AJAX提交的实现方法
2016/10/24 Javascript
微信小程序网络层封装的实现(promise, 登录锁)
2019/05/08 Javascript
vue router-link 默认a标签去除下划线的实现
2020/11/06 Javascript
Python异常学习笔记
2015/02/03 Python
python pandas dataframe 行列选择,切片操作方法
2018/04/10 Python
python控制windows剪贴板,向剪贴板中写入图片的实例
2018/05/31 Python
.dcm格式文件软件读取及python处理详解
2020/01/16 Python
python使用html2text库实现从HTML转markdown的方法详解
2020/02/21 Python
python opencv实现直线检测并测出倾斜角度(附源码+注释)
2020/12/31 Python
python实现三种随机请求头方式
2021/01/05 Python
世界最大的票务市场:viagogo
2017/02/16 全球购物
伦敦香水公司:The London Perfume Company
2019/11/13 全球购物
教师新年寄语
2014/04/03 职场文书
公务员年度考核登记表个人总结
2015/02/12 职场文书
比赛主持人开场白
2015/05/29 职场文书
2015年新农村建设指导员工作总结
2015/07/24 职场文书
《鸟的天堂》教学反思
2016/02/19 职场文书
Mysql基础之常见函数
2021/04/22 MySQL
Golang并发工具Singleflight
2022/05/06 Golang
python index() 与 rindex() 方法的使用示例详解
2022/12/24 Python