码迷,mamicode.com
首页 > 编程语言 > 详细

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

时间:2016-01-30 13:53:45      阅读:219      评论:0      收藏:0      [点我收藏+]

标签:

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

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

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

 

这一系列的文章主要是针对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 , 第一章(估计要写9章)

标签:

原文地址:http://www.cnblogs.com/zhgangxuan/p/gxtemplate_01.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!