中级JavaScript例子, 如何实现一个简单实用的模板套用机制, GXTemplate , 第一章(估计要写9章)

原创 2016年01月30日 11:21:25

我们是刚刚成立的, 一家传统的软件开发公司(只有几个人的小公司), 主营业务就是传统行业软件项目的外包.

由于这种项目需要的技术不深, 但是对开发效率有很高的要求, 所以我们在慢慢的摸索一下快速开发模式.

同时也愿意把其中不杂乱的部分,分享出来. 

 

这一系列的文章主要是针对GXTemplate, 一个模板套用类库 (谈不上框架)

这并不是一个 "如何使用" 的教程 , 而是一个 "如何创造" 这种类库的教程.

特点是, 我们会把整个创造过程, 由v0.1的原始版本开始, 一步一步如何加代码的, 逐渐展示给大家观看.

如果大家是初学者, 想在JavaScript方面有进一步的提高, 那么可以持续关注一下这系列的教程.

 

首先最初的版本v0.1是这个样子的: (v1.0已完成. 但教程要分开多篇编写)

下载地址  https://github.com/zhgangxuan/GXTemplate/blob/master/_oldfiles/version1/template01.html 

源代码 (默认折叠,请展开): 

<!DOCTYPE html>
<html>
<head>
	<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
	<title>text node</title>

	<script src="data.js"></script>
</head>

<body>

	<h1>{#myitem.name}</h1>
	<p>
		Address: {#myitem.address}
		-
		Zip: {#myitem.zipcode}
		-
		Phone: {#myitem.phone}
	</p>

</body>


<script>

	var re_template_textbinding = /{#([^}]+)}/g;

	function ProcessEval($__exp__) {
		return eval($__exp__);
	}

	function ProcessTextNode(node, str) {
		var newstr = str.replace(re_template_textbinding, function (exp, g1, index, full) {
			return ProcessEval(g1);
		});
		if (newstr != str) node.nodeValue = newstr;
	}

	function TemplateExecute(node) {

		if (node.nodeType == 3) {
			var str = node.nodeValue;
			if (str.indexOf('{#') != -1)
				ProcessTextNode(node, str);
			return;
		}

		if (node.nodeType != 1)
			return;
		switch (node.nodeName) {
			case "SCRIPT":
			case "STYLE":
				return;
		}

		var cns = node.childNodes;
		for (var ni = cns.length; ni > 0; ni--)
			TemplateExecute(cns.item(cns.length - ni));

	}


	TemplateExecute(document.body);


</script>


</html>

  

目标 :

让文本内容支持 {#脚本返回值} 这个语法

这样我们就可以避免在页面中放太多带id的span, 和在分离的JS代码中去设置这个span的innerText了.

在快速开发的角度上, 代码越少, 越不分离, 就越好

 

实现过程:

由于在脚本执行的时候, HTML代码已经转化为具体的DOM对象了. 所以我们的策略是直接对DOM树进行递归.

 

在例子里, 从document.body开始搜索, 把整个文档都搜个遍. (但实际使用时建议从一个小范围内进行处理)

	TemplateExecute(document.body);

 

TemplateExecute里的递归方式, 是倒数方式.  先从倒数第n项开始, 然后是第n-1项, 然后是第n-2,...一直到倒数第一项.

		var cns = node.childNodes;
		for (var ni = cns.length; ni > 0; ni--)
			TemplateExecute(cns.item(cns.length - ni));

  

在执行的过程中, 如果遇到一些不需操作textnode的Element, 也要跳过

		switch (node.nodeName) {
			case "SCRIPT":
			case "STYLE":
				return;
		}

 

在递归的过程中, 如果找到textnode, .nodeName=="#text"或 .nodeType==3, 那么就执行ProcessTextNode函数

		if (node.nodeType == 3) {
			var str = node.nodeValue;
			if (str.indexOf('{#') != -1)
				ProcessTextNode(node, str);
			return;
		}

str.indexOf('{#')是一个快速跳过没有指令的内容的过程, 实测能提高性能.  

 

在ProcessTextNode内, 使用正则表达式 var re_template_textbinding = /{#([^}]+)}/g; 去替换掉所有 {# ... } 表达式

如果有满足的表达式并且执行脚本后的文本和原来不同,  那么使用node.nodeValue = newstr就可以改写textnode要显示的文本

	function ProcessTextNode(node, str) {
		var newstr = str.replace(re_template_textbinding, function (exp, g1, index, full) {
			return ProcessEval(g1);
		});
		if (newstr != str) node.nodeValue = newstr;
	}

  

而ProcessEval目前很简单, 只是使用JavaScript的内置函数eval执行一下. 以后会有更好的方式.

	function ProcessEval($__exp__) {
		return eval($__exp__);
	}

 

具体的数据myitem是定义在data.js里, 被后续的例子共同引用:

var myitem = { name: "mobile shop", address: "No.1234 Fenghuang Road", zipcode: "519000", phone: "0756-0000000" };

 

这个例子运行了之后的显示结果是这样的

<h1>mobile shop</h1>
<p>Address: No.1234 Fenghuang Road - Zip: 519000 - Phone: 0756-0000000</p>

  

我们想逐渐建立起一套简单易用的, 适合传统项目的ASP.NET+C#+JavaScript的开发方案. 

网上各种开源框架虽然厉害, 但是对于新手来说却很难很花时间. 

因为对于很多中小软件公司来说, 他们经常会招到一些入门开发者. 太复杂的框架不适合人员调动或二次开发.

所以我们不惜花时间去重做这些东西. 希望能帮助到国内的初级开发者, 为国内的信息化建设贡献点绵力.

 

实际上整个GXTemplate的v1.0版都已经上传到github的了.  接下来我们的业余时间主要是谢谢例子, 写写教程. 

对于不懂得使用github的朋友, 可以直接下载源代码 https://github.com/zhgangxuan/GXTemplate/archive/master.zip  

  

 

中级JavaScript例子, 如何实现一个简单实用的模板套用机制, GXTemplate , 第4章(估计要写9章)

第4章 接 第2章 http://blog.csdn.net/zhgangxuan/article/details/50636985  第4章 下载地址  https://github.c...
  • zhgangxuan
  • zhgangxuan
  • 2016年02月05日 09:36
  • 124

中级JavaScript例子, 如何实现一个简单实用的模板套用机制, GXTemplate , 第2章(估计要写9章)

接 第1章 http://blog.csdn.net/zhgangxuan/article/details/50610883  第2章 下载地址  https://github.com/zh...
  • zhgangxuan
  • zhgangxuan
  • 2016年02月01日 23:59
  • 209

中级JavaScript例子, 如何实现一个简单实用的模板套用机制, GXTemplate , 第3章(估计要写9章)

接 第2章 http://blog.csdn.net/zhgangxuan/article/details/50621124  第3章 下载地址  https://github.com/zh...
  • zhgangxuan
  • zhgangxuan
  • 2016年02月05日 09:19
  • 222

《机器学习实战》第一章 – 机器学习基础

print("Hello Machine");我一直相信, 兴趣是最好的老师!所以对新事物开始的学习,我总喜欢以问题为导向,“所学的东西到底能帮我们解决什么问题?”来引导我不断学习新知识,等有一定理解...
  • u013550998
  • u013550998
  • 2017年02月06日 21:16
  • 151

用javascript实现简单计算器

这是一个简单计算器的实现。可以实现简单的加,减,乘,除功能,用户按下“←”按钮,删除当前算术表达式最后一个字符,并更新显示,用户按下“CE”按钮,清除当前算术表达式,如果算术表达式非法,弹出警告框提醒...
  • XHF901
  • XHF901
  • 2016年12月09日 15:49
  • 328

类模板的简单例子(作业)

#include using namespace std; template class shuju{ public: T data; shuju *next; }; template class...
  • normol
  • normol
  • 2016年04月26日 15:25
  • 780

Spring中的简单实现AOP小例子

Spring中的简单实现AOP小例子
  • starjuly
  • starjuly
  • 2016年08月31日 23:37
  • 1721

JavaScript的异步实现

我们经常说JS是单线程的,比如node.js研讨会上大家都说JS的特色之一是单线程的,这样使JS更简单明了,可是大家真的理解所谓JS的单线程机制吗?单线程时,基于事件的异步机制又该当如何,这些知识在《...
  • gongzhuxiaoxin
  • gongzhuxiaoxin
  • 2016年08月31日 16:31
  • 658

javaScript简单实例:实现一个简易计算器

javaScript简单实例:实现一个简易计算器**样式代码** body{ font-size:12px; font-family:Arial, ...
  • SUN_song520
  • SUN_song520
  • 2015年09月17日 20:55
  • 3737

《统计学习方法》第一章习题

《统计学习方法》第一章习题
  • u012538116
  • u012538116
  • 2017年04月30日 14:39
  • 1068
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:中级JavaScript例子, 如何实现一个简单实用的模板套用机制, GXTemplate , 第一章(估计要写9章)
举报原因:
原因补充:

(最多只允许输入30个字)