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

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

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

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

这一系列的文章主要是针对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

  

时间: 2024-10-23 09:26:41

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

开发一个简单实用的android紧急求助软件

之前女朋友一个人住,不怎么放心,想找一个紧急求助的软件,万一有什么突发情况,可以立即知道.用金山手机卫士的手机定位功能可以知道对方的位置状态,但不能主动发送求助信息,在网上了很多的APK,都是鸡肋功能,都需要解锁.并打开软件,真正的紧急情况可能没有时间来完成这一系列操作. 于是我自己做了一个这样的软件,在紧急情况下,连续按电源键5次即可发送求救短信和位置信息给事先指定的用户,这个操作在裤兜里就能完成.原理很简单,就是设置监听器捕获屏幕的开关,在较短的时间内屏幕开关达到一定次数后,触发手机定位,定

一个简单的makefile模板

在Linux下编译工程,makefile是必不可少的工具,下面记录一个简单的makefile模板. 多个文件目录下的makefile写法推荐参考博文:http://www.cnblogs.com/Anker/p/3242207.html DIR_SRC = ./ DIR_BIN = ../bin PROGRAMNAME = program TARGET = ${DIR_BIN}/${PROGRAMNAME} SRC = $(wildcard ${DIR_SRC}/*.cpp) CC = g++

Html+css 一个简单的网页模板

一个简单的网页模板,有导航.子菜单.banner部分 1 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 2 "http://www.w3.org/TR/html4/loose.dtd"> 3 <html> 4 <head> 5 <title>网页</title> 6 <meta charset="UTF-8&qu

LogCook 一个简单实用的Android日志管理工具

众所周知,日志的管理是软件系统很重要的一部分,千万不可忽略其重要性.完整的日志将会在系统维护中起着异常重要的作用,就好像磨刀不误砍柴工一样,日志就像对系统进行分析的工具,工具便捷了,对系统分析起来就能达到事半功倍的效果.开发者必须要明白日志的价值和意义,万万不可忽略和轻视. LogCook是一款非常简洁实用的Android日记管理工具.LogCook的中文翻译是日志厨师,你可以把它看作是一个日志美食家. 特点 作为一款日志管理工具它最大的特点就是简单实用,与Android原生的日志功能相比较它具

编写一个简单的js模板替换工具 rtt----replace templete tool

最近一段时间在修改自己的个人在线简历.  这个在线简历用到了css3来制作3D的旋转效果, 因此会有兼容性问题, 针对于不支持css3的3D透视的浏览器, 比如 IE,  360等等, 我使用的是另一套css文件兼容.  针对于移动端浏览器, 尽管基本都是webkit内核, 但经测试发现3D效果并不流畅, 因此移动端是识别userAgent切换到另一套非3D页面.  因为没用任何数据库, 那么问题就来了, 移动端和pc端两套页面是共用的一套数据, 我想到的方法有两个: 一是页面加载之后用ajax

[bootstrap] 打造一个简单的系统模板(1) 左侧折叠菜单

1. 前言 最近需要做一个后台管理系统,我打算使用bootstrap弄一个好看的后台模板.网上的好多模板我觉的css和js有点重. 于是就打算完全依靠bootstrap搭建一个属于自己的模板. 首先从左侧的折叠菜单开始.看图. 2. CSS 代码 以下是自定义的css代码,由于系统是内部使用,所以优先考虑chrome,firefox 不考虑IE了. #main-nav { margin-left: 1px; } #main-nav.nav-tabs.nav-stacked > li > a {

一个简单的PHP模板引擎

PHP早期开发中通常是PHP代码和HTML代码混写,这也使代码中充斥着数据库操作,逻辑处理等.当项目不大时,这样的代码还可以接受,但是随着项目不断扩大,我们就会发现同一个文件中同时存在前端逻辑和后端处理,当逻辑越来越复杂时,代码的可读性和可维护性都会变得非常差,以至于后来不得不进行大规模的代码重构.所以后来就出现了代码分层的思想,尽量拆分开前端代码和后端代码. PHP模板引擎能解决这种混乱吗?当然可以.但是呢,即使你不用专门的模板引擎也可以写出逻辑清晰的代码,重点是要有分层的思想,有专门的脚本去

一个简单实用的图片切换小例子

不经意间看到了以前写的这个小东西,就贴上来了,支持点击切换和自动轮播,供前端新手看看吧! 代码如下: <div class="scroll_div"> <ul class="pic"> <li><img src="img/pic_1.jpg" /></li> <li><img src="img/pic_2.jpg" /></li>

Golang的一个简单实用的http客户端库httpc

httpc简介 httpc这是一个发起http请求的客户端库.它具有的特色包括:简单易用.易于扩展.支持链式调用.支持多种格式的处理等.特别适合用来调用restfull风格的接口. 项目地址 https://coding.net/u/recallsong/p/httpc/git 下载 go get git.coding.net/recallsong/httpc.git Api文档 查看Api文档 我们也可以利用godoc工具在本地查看api文档: godoc -http=:9090 在浏览器中查