做了几年开发, 平时看着会做框架的高手,那个羡慕妒忌恨呀,有闲的时候,总会想,要是自己能做一个框架该多好呀,经过一段时间的积累,有了一点点进步,于是决定亲手开发一个框架,本系列主要做一些初步的框架,希望自己学习,希望也能帮到跟我一样有梦想的人。
所谓框架,就是基于它,能很方便的进行业务开发,减少技术上的时间花费,通过了解那么多框架后, 你是否也有想从0开始,自己开发一个呢!如果有,那就一起来吧,也许会有很大乐趣哦。
此次要做的框架,是前端javascript框架,面向的是,大型应用前端界面,比如数据编辑,数据查询,数据管理等用到的前端控件及功能,有两个主要的目的, 第一, 简化web页面上的布局设计,第二,把应用尽可能的控件化,框架的开发思路是先做框架的布局,再开发具体的控件,接着扩展页面的控制,
现在开始我们的控件框架之旅。
先创建如下目录结构。
+--demo
+--script
+--common
+--init.js
+--css
+--web
+--test.html
以demo做为我们的框架的根目录,
script做为所有js的根目录,
script目录下的common目录作为框架基础目录,框架用到的文件都放置于此,css文件用于存放样式文件,
web则是页面目录,
整个框架中,需要一个起始js文件,这个文件将是我们框架的入口,起到初始化,加载,运行的作用,我们把文件命名为init.js并放在common目录下,
在init.js文件里定义第一个对象scriptUtil;该对象有三个属性,
1. js脚本加载列表,
2. css文件加载列表,
3. 控件对象列表,
如下:
function scriptUtil() {
//加载导入的js列表
this.scriptList = {};
//加载的css列表
this.cssList = {};
//创建的控件类
this.com = {};
};
接着,编写一个页面test.html用于测试,并且引入init.js文件,放到web目录下
<!DOCTYPE html>
<head><title>test</title>
<script src="../script/common/init.js" type="text/javascript"></script>
</head>
<body>
</body>
</html>
为了能够清楚加载的情况, 给对象scriptUtil添加一个日志输出的函数和一个加载成功的判断函数;
scriptUtil.prototype = {
/**
* 日志输出.
* 参数 src 字符串
*/
LogInfo : function(src) {
if(window.console.info) {
window.console.info(src);
}
},
/**
* 是否加载判断.
* 参数 src 加载的文件名
*/
isImport : function(src) {
return (typeof this.scriptList[src] != "undefined"
|| typeof this.cssList[src] != "undefined");
}//方法之间用逗号隔开
}
再添加一个文件类型判断函数,目前仅包括css, js两种文件
scriptUtil.prototype = {
//之前添加过的方法
/**
* 文件类型.
* 参数 scr 文件路径
*/
scrType : function(scr) {
var scrAry = scr.split(".");
if (scrAry.length > 1) {
return scrAry[scrAry.length - 1].toUpperCase();
} else {
return "";
}
} //方法之间用逗号隔开,
}
我们用的是普通的目录结构,因此需要处理相对路径的问题,添加一个获取根目录路径的函数(dome目录),
这里用到了算法, 首先,我们有两个路径, 一个是html文件的路径 即test.html的路径,另一个是js初始化文件的路径,即init.js的路径,通过这两个文件的路径,用来分析出整个工程的相对路径,
1. 先判断是不是全路径,既http开头,或f:开头,
2. 如果是,就从开始循环找到第一个不相同的目录,
3. 通过html路径的相对深度,找到js文件,需要回退文件夹(../)的层次
4. 拼成完成的js相对路径。
scriptUtil.prototype = {
//之前添加过的方法
getPath : function() {
//获取默认的init.js文件路径
var srcUrl = document.getElementsByTagName("script")[0].src;
var re = /[\/\\]+/g;
//判断是否是硬盘,或服务器上的URL
if (/([a-zA-Z]:)|([hH][tT][tT][pP]:\/\/)/.test(srcUrl)) {
//获取html的URL
var docUrl = document.URL;
//拆分成数组
var srcAry = srcUrl.split(re);
var docAry = docUrl.split(re);
var indexs = 0;
//循环找到第一个不相同的目录
for ( var i = 0,
len = srcAry.length < docAry.length ? srcAry.length
: docAry.length;
i < len; i++) {
if (srcAry[i] !== docAry[i]) {
indexs = i;
break;
}
}
//test.html目录回寻到根目录
var path = "";
for ( var i = indexs, len = docAry.length; i < len - 1; i++) {
path = path + "../";
}
//完善js的目录
for ( var i = indexs, len = srcAry.length; i < len - 1; i++) {
path = path + srcAry[i] + "/";
}
return path;
} else {
//如果是相对目录,则直接使用。
var srcAry = srcUrl.split(re);
var path = "";
for ( var i = 0, len = srcAry.length; i < len - 1; i++) {
path = path + srcAry[i] + "/";
}
return path;
}
},
}
通过上面的路径函数,可以得到要加载的路径, 接下来要做的就是把文件加载进来,即import函数,函数需要三个参数,第一个参数, 可以传一个或多个文件名, 第二个参数,是回调函数,第三个是相对路径,因为路径不一定需要,因此放在第三个参数上,这里的实现算法是,
1. 拿第一个文件,判断文件类型
2. 生成对应的script或link对象,绑定onload和onerror事件
3. 添加到<head>标签上,
4. 在绑定的事件激活后,记录加载的文件,递归下一次调用,
5. 如果加载完了,调用回调函数
scriptUtil.prototype = {
//之前添加过的方法, 用逗号隔开
/**
* 加载文件,
* 参数 src 加载的文件,字符串或数组,
* 参数 callBack 回调函数,
* 参数 sPath 指定路径 默认为空
*/
Import : function(src, callBack, sPath) {
//路径
if(typeof sPath == "undefined") sPath = "";
//转换成数组
var src = src || [];
if(typeof src == "string") {
src = [src];
}
//获取head元素
var _doc = document.getElementsByTagName("head")[0];
var importObj = {};
if(src.length > 0) {
var curSrc = sPath + src[0];
//删除数组内第一个文件名
src.splice(0, 1);
var srctype = this.scrType(curSrc);
if(typeof this.scriptList[curSrc] === "undefined"
&& typeof this.cssList[curSrc] === "undefined") {
//如果没有加载过
if ("JS" == srctype) {
//加载js文件
importObj = document.createElement("script");
importObj.type = "text/javascript";
importObj.language = "javascript";
importObj.src = curSrc;
this.scriptList[curSrc] = 0;
} else if ("CSS" == srctype) {
//加载样式文件
importObj = document.createElement("link");
importObj.rel = "stylesheet";
importObj.type = "text/css";
importObj.href = curSrc;
this.cssList[curSrc] = 0;
}
//保存相关对象到importObj中
importObj.csrc = curSrc;
importObj.cstype = srctype;
importObj.self = this;
//加载成功事件
importObj.onload = importObj.onreadystatechange = function() {
var csrc = this.csrc;
if(!this.readyState||this.readyState=='loaded'
||this.readyState=='complete'){
var cst = this.cstype;
var Self = this.self;
//打上加载成功标志
if ("JS" == cst) {
Self.scriptList[csrc] = "sucess";
Self.LogInfo("import script " + csrc + " sucess.");
} else if ("CSS" == cst) {
Self.cssList[csrc] = "sucess";
Self.LogInfo("import css " + csrc + " sucess.");
}
this.onload=this.onreadystatechange=null;
//继续加载后续文件,
if(src.length > 0) {
Self.Import(src, callBack, sPath);
} else if(typeof callBack == "function") {
callBack(true);
}
this.self = null;
}
}
//导入错误的事件
importObj.onerror = function() {
var Self = this.self;
var csrc = this.csrc;
var cst = this.cstype;
//打上加载成功标志
if ("JS" == cst) {
Self.scriptList[csrc] = "error";
Self.LogInfo("import script " + csrc + " error.");
} else if ("CSS" == cst) {
Self.cssList[csrc] = "error";
Self.LogInfo("import css " + csrc + " error.");
}
//清除加载失败的文件
_doc.removeChild(importObj);
this.onerror = null;
//继续加载后续文件,
if(src.length > 0) {
Self.Import(src, callBack, sPath);
} else if(typeof callBack == "function") {
//回调
callBack(true);
}
this.self = null;
}
//添加加载文件到head中
_doc.appendChild(importObj);
} else {
if(src.length > 0) {
this.Import(src, callBack, sPath);
} else if(typeof callBack == "function") {
callBack(true);
}
}
} else if(typeof callBack == "function") {
callBack(true);
}
}// Import
}
到此, 一个完整的动态加载对象已编写完成,
请关注下一篇,我们将编写如何使用这个对象把更多的js导入到html页面中。
分享到:
相关推荐
第一篇 javascript控件开发之动态加载
由于网页中很难实现进度条的添加,所以开发了一个com组件来实现网页中加载进度条控件
vs2010开发activex(MFC)控件/ie插件(一),测试ocx控件加载 vs2010开发activex(MFC)控件/ie插件(二),js传参数 vs2010开发activex(MFC)控件/ie插件(三),js调用ocx控件的接口函数
该控件为标准ActiveX控件, 完美实现和封装了软电话功能 可用Delphi, VB, VC, .net, java等语言加载和调用 ...Demo版每次加载只支持接听/拨打3次, 超过次数后需要重新加载控件 (开发过程中可能需要关闭工程再重新打开)
学习ReactNative的一个初始的项目,运用基本控件加载网络数据并显示
dotNetFlexGrid是一款asp.net原生的异步表格控件,它的前身是Jquery FlexiGrid插件,我们重构了FlexiGrid的大部分Javascript代码,使其工作的更有效率,BUG更少;同时将其封装为asp.net 控件,提供了简单易用的使用...
制作一个ActiveX控件,在网页中安装加载,然后可以通过javascript访问,设置ActiveX控件中的时间显示; 2.介绍C#如何在ActiveX控件中调用javascript的函数; 3.ActiveX版本更新; 4.测试ActiveX控件在新版操作系统上...
jsTree是基于javascript的一个跨浏览器树控件,功能强大,既可以一次性把所有节点都加载到客户端,也可以只加载一层,点击节点后再去服务端获取下层节点。
示例描述:介绍JavaScript与表单控件。 6.1.html JavaScript获取文本框的值。 6.2.html JavaScript控制文本框。 6.3.html 文本框的JavaScript特效。 6.4.html 获取select元素的值。 6.5....
1.加载脚本文件 2.获取脚本中的函数列表 3.获取脚本中的全局变量列表 4.按变量名称 设置、获取 脚本文件里的全局变量值 5.直接执行 文本、变量 中设置的脚本代码 6.能获取文本脚本执行结束后脚本里面的变量返回值,...
该软件完全按照国家办公/政务软件对公文文档需求标准设计,是目前国内功能最先进、用户界面最友好的在线文档编辑控件,成为许多软件开发商开发电子政务/办公软件(OA)的首选标准控件。 SOAOFFICE 文档控件,能够在...
第1章 JavaScript简介 1 1.1 JavaScript是什么 1 1.2 JavaScript不是什么 2 1.3 JavaScript的用处 3 1.4 JavaScript及其在Web页面中的位置 3 1.5 Ajax是什么 5 1.6 JavaScript是什么样子的 6 1.7 ...
2、显示动态地图服务的图层节点的异步加载。 3、对地地图服务的地图图层进行进行显示控制。 4、使用标准JSON格式进行地图服务配置。 5、改图层树基于Jquery zTree开发。 压缩包中包括代码文件和配置文件,解压密码同...
开发环境:、Dreamwave、Notepad、UltraEdit,或者其他文本编辑器 Web服务器:IIS 5.1及以上版本 2.本书所附光盘范例 第1章(\1) 示例描述:变量。 1_1.htm 变量声明。 1_2.htm 局部变量和全局变量。 1_3....
iSmartJs是一个全栈式的开发框架,提供了诸如AJAX动作监听、消息通知、页面动态加载、UI交互机制等整体化的RIA架构, 控件的设计与使用可以在很大程度上减少js代码量,从而提高开发速度。 2、模块化页面 ...
javaScript实例自学手册代码,加了个index.html方便搜索 内容如下面的。 ... 1.19 在网页中动态添加Script脚本.htm ... 1.20 用JavaScript随机修改页面的标题.htm... 2.17 动态设置控件的事件.htm 2.2 按回车调用登录按钮.htm
本文档将对EXTJS的实用开发指南进行总结,涵盖了EXTJS的基础知识、控件、工具和实用开发技巧。 一、EXTJS基础知识 在使用EXTJS框架之前,需要在HTML页面中引入EXTJS的CSS和JavaScript文件,这些文件通常位于extjs...
22.如何实现从服务器端向页面动态添加javascript脚本-示例1 22.如何实现从服务器端向页面动态添加javascript脚本-示例2 24.如何处理多页面重定向到同一页面后的返回问题 25.如何用Response.Redirect方法传递汉字 ...
调研安卓(Android)平台上,JavaScript开源库iCharts和eCharts表现和性能测试的代码,使用WebView加载
新的IO组件在处理磁盘中的文件时,将不必再对文件执行I/O操作,这意味着在对文件进行处理时将不必再为文件申请并分配缓存,所有的文件缓存操作均由系统直接管理,由于取消了将文件数据加载到内存、数据从内存到文件...