前端Javascript模板引擎

前端开发  |  6年前

说起模板,很多人会认为这是后台的东西(如PHP的Smarty、Java的Velocity),跟前端没有关系。然而,随着前端的逻辑变得越来越复杂,引入模板引擎已经是非常必要了。

模板引擎的主要功能就是把变化的数据融入到不变的模板中,并生成最终结果。目前,前端的主要数据格式无非是XMLJSON

如果选择XML作为数据格式,XSLT就是最佳的模板语言,但XML+XSLT的缺点非常明显:

  • 兼容性问题。XML+XSLT在不同浏览器下的转换方式有所不同。
  • XML、XSLT的语法都是极其冗余的,数据量相对较大。

如果选择JSON作为数据格式,就没有原生的模板语言可用了,只能生拼字符串。例如,把下面代码中的data转换成一个表格:

var data = [
	{ id : 1, name : 'Google', url : "google.com" },
	{ id : 2, name : '百度', url : "baidu.com" },
	{ id : 3, name : '有道', url : "youdao.com" }
], html = [ ];

html.push('<table>');
for (var i = 0; i < data.length; i++) {
	html.push('<tr>');
	html.push('<td>', data[i].id, '</td>');
	html.push('<td><a href="http://', data[i].url, '" target="_blank">', data[i].name, '</a></td>');
	html.push('</tr>');
}
html.push('</table>');

document.write(html.join('\r\n'));
3936次阅读,7条评论

再论Javascript的类继承

前端开发  |  7年前

说到Javascript的类继承,就必然离不开原型链,但只通过原型链实现的继承有着不少缺陷。

无参数类继承的问题

先看一段示例代码,实现B继承于A:

function A() {
}
A.prototype.a1 = function() { };

function B() {
}
B.prototype = new A();
B.prototype.b1 = function() { };

var b = new B();
alert(b.constructor == A); // true
alert(b.constructor == B); // false

这段代码的主要问题是:

  • 需要实例化A作为B的原型,此时就执行了A的构造函数。但按照面向对象的规则,实例化B之前,B及其父类A的构造函数都不应该执行
  • 更改了B的prototype,导致b.constructor不是B而是A
445次阅读,2条评论

Opera下的max-width BUG

前端开发  |  7年前

昨晚着手给个人博客增加网易微博的调用,在Opera下却出现了一个意想不到的问题。内容的展示,一开始是做成横向不间断滚动(现在已经改成纵向定时滚动了)。

不间断滚动的原理这里不详细说了,其中一个必要的条件是,进行滚动的内容容器要设置得很宽,这样才能使内容排在一行。一般情况下,几千像素也够了,但是微博的信息可能很长,况且一读就有好几十条,这宽度非得设成几万像素不可。

虽然数字比较大,但是在Firefox、IE中测试过后也是没问题的,唯独是Opera下出现了悲剧:

Dragonfly

390次阅读,2条评论

使用参数化查询防止SQL注入漏洞

其他开发  |  7年前

SQL注入漏洞曾经是Web应用程序的噩梦,CMS、BBS、Blog无一不曾受其害。

SQL注入的原理

以往在Web应用程序访问数据库时一般是采取拼接字符串的形式,比如登录的时候就是根据用户名和密码去查询:

string sql = "SELECT TOP 1 * FROM [User] WHERE UserName = '" + userName + "' AND Password = '" + password + "'";

其中userName和password两个变量的值是由用户输入的。在userName和password都合法的情况下,这自然没有问题,但是用户输入是不可信的,一些恶意用户只要用一些技巧,就可以绕过用户名、密码登录。

假设password的值是"1' or '1' = '1",userName的值随便取,比如是"abc",那变量sql的值就是:

SELECT TOP 1 * FROM [User] WHERE UserName = 'abc' AND Password = '1' or '1' = '1'

由于'1' = '1'恒为真,因此只要User表中有数据,不管UserName、Password的值是否匹配,这条SQL命令准能查出记录来。就这样,登录系统就被破解了。

4292次阅读,3条评论

HTML在线编辑器的实现难点

前端开发  |  7年前

HTML在线编辑器实际上是什么

其实有好几种实现方式,目前用得最多、兼容性最好的还是iframe方式。

<iframe src="" frameborder="0"></iframe>

只有这个空iframe是不行的,还要用Javascript把它设成可编辑:

iframe.contentWindow.document.designMode = "on";
iframe.contentWindow.document.contentEditable = true;

换而言之,HTML在线编辑器就是一个可编辑的iframe

1828次阅读,6条评论

输入法也做代码库

前端开发  |  7年前

像Visual Studio、Dreamweaver、EditPlus这些IDE都是有代码库功能的,平时把一些常用的代码片段收藏到库里面,需要用的时候可以一键插入到上下文,无需重新编写。

然而,比较麻烦的是,这些IDE的代码库都是相互独立的,比如在Dreamweaver里面录入的代码片段,就无法直接插入到Visual Studio里面去。那有没有独立的代码库软件,可以跟所有IDE整合呢?很遗憾,我没有找到,如果看到此篇文章的你找到了,请顺便告诉我。

虽然没有专门的代码库软件,可我后来发现了功能类似的工具——输入法里面的自定义短语。当然,只有紫光、搜狗、QQ拼音这些现代化输入法才有这个功能,像Windows自带的那些八、九十年代的输入法是不行的。

搜狗拼音的高级设置

1209次阅读,3条评论

从表单数据创建实体对象

其他开发  |  7年前

Web应用的基本流程就是通过表单提交数据到服务器,服务器端程序以这些数据建立实体对象,经过处理后更新到数据库。而从表单数据创建实体对象的过程通常是很麻烦的,必须考虑到以下几点:

  1. 创建什么类型的对象?
  2. 表单的各项数据如何映射到对象的各项属性?
  3. 提交到服务器的数据都是字符串类型的,要还原成对应属性的数据类型。

之前我就用泛型写了一个Request工具类。不过这个类仅仅是解决了第三个问题而已,而要解决前两个问题就得靠反射了。

要解决第一个问题,还得用泛型,也就是类型作为参数传入,由此得到这个通用函数的原型:

public class ReqHelper
{
  public static T GetEntity<T>()
  {

  }
}

而函数体的第一步,自然就是建立类型T的示例:

T entity = new T();

这段代码乍一看没错,但一编译就会报错,原因是编译器并不能确定T的构造函数的原型。因此还得用where关键字进一步约束T:

public static T GetEntity<T>() where T : new()
{
  T entity = new T();
}
598次阅读,1条评论

再论Javascript下字符串连接的性能

前端开发  |  7年前

这是个老话题了,之所以再拿出来说,是因为浏览器一直在进步,以前最好的方法现在不一定是最好的。

1 如何进行字符串连接?

首先让我们来回顾一下字符串连接的两种常用方法:

1.1 使用字符串连接运算符

常用的语言(如Java、C#、PHP等)都有字符串连接运算符,Javascript也不例外,代码示例:

var str = "";
str = str + "a";

1.2 使用数组

在常用的语言中,字符串连接运算的性能普遍不高,为此在C#中就专门提供了StringBuilder(Java中提供了StringBuffer)用于连接字符串。而在Javascript中就出现了通过Array模拟StringBuilder的方案

var str = [];
for (var i = 0; i < 100; i++) {
  str[i] = "12345";
}
str = str.join("");
2877次阅读,6条评论

淘宝搜索框研究报告

前端开发  |  7年前

在输入框里面预设一段提示文字,当焦点在输入框的时候清空这段文字,这在目前来说已经不是什么新鲜事了。淘宝的搜索框就用到了这样一种设计:

淘宝搜索框

这种设计一般是用javascript监控了输入框的focus和blur事件:

<input type="text" id="q" value="请输入关键字" />
<script type="text/javascript">//<![CDATA[
$("#q").onfocus = function() {
  if ("请输入关键字" == this.value) {
    this.value = "";
  }
};
$("#q").onblur = function() {
  if ("" == this.value) {
    this.value = "请输入关键字";
  }
};
//]]></script>

这段代码有两个很明显的缺点:

  1. “请输入关键字”这段提示共出现了3次,一旦要改这段文字就得改3个地方,维护显得非常不便
  2. 为了性能优化,我们会把javascript部分放到页面末尾。然而,像门户网站首页这种代码量很大的页面,末尾的javascript很可能会延时1-2秒执行。在这段时间内,即使焦点在输入框内,提示文字也不会消失,用户需要手动删除这段文字再输入内容
1100次阅读,2条评论

使用泛型打造Request工具类

其他开发  |  7年前

在ASP.NET页面中可以使用Request对象获取指定参数的值,例如:

string value = Request["id"];

参数值都是string类型,但是进行处理的时候可能要转换成数字、日期等类型。

string value = Request["id"];
int id = Int32.Parse(value);

实际应用的时候还要考虑异常的情况。

string value = Request["id"];
int id;
Int32.TryParse(value, out id);

如果每个页面都这么写,显得非常麻烦,代码重复也很严重,还是封装成一个工具类吧。

public class ReqHelper
{
	public static string GetString(string paramName) { ... }
	public static int GetInt(string paramName) { ... }
	public static bool GetBool(string paramName) { ... }
	...
}
813次阅读,1条评论