有没有可能写一套代码适应以下三种情况:
1. 客户端没有开启javascript,或者使用ucweb一类的弱智浏览器访问时,功能没有影响
2. 客户端开启了javascript,每个页面都有单独加载的js,但是禁用ajax,只帮助用户交互
3. 客户端开启了javascript,为了提高载入速度,尽量使所有操作用ajax完成
略有所得: http://www.blogo2.com
源代码: http://code-of-emptyhua.googlecode.com/svn/trunk/blogo2
没有禁用js的时候,页面切换,表单提交(注册和登录没有用)尽量的使用ajax,而且部分操作会使用弹层(登录后的管理),禁用js之后,则所有操作换成普通表单提交在页面之间跳来跳去。。
还有一个功能没有开启,就是可以选择不用ajax,但是独立开的页面js依然有效。
有兴趣的同学可以check源代码,这种模式的实现:
1. 开发的时候禁用ajax,单个页面开发,而且要求禁用js时业务可以走通,页面内的js和css统一由模板引入。
2. 对需要开启ajax的链接增加hook,例如data-ajax=”dialog:{}”,则表明在开启ajax模式后,点击这个链接需要弹窗
3. ajax模式下只需要对单个页面更换特有的模板,动态加载需要的js和css即可。
这种设计的特点:
1. 尽量一个人包前后端。。
2. json不潮了,ajax返回html代码,优点是js不用套页面了,缺点是流量大
over,虽然没有完美的代码,但是我尽量~
———–
post by gmail~
做前端的同学都应该听说或者用过,是一段脚本,可以让ie实现css3里的圆角和阴影效果:http://fetchak.com/ie-css3/
用法大致如下
.box {
-moz-border-radius: 15px; /* Firefox */
-webkit-border-radius: 15px; /* Safari and Chrome */
border-radius: 15px; /* Opera 10.5+, future browsers, and now also Internet Explorer 6+ using IE-CSS3 */
-moz-box-shadow: 10px 10px 20px #000; /* Firefox */
-webkit-box-shadow: 10px 10px 20px #000; /* Safari and Chrome */
box-shadow: 10px 10px 20px #000; /* Opera 10.5+, future browsers and IE6+ using IE-CSS3 */
behavior: url(ie-css3.htc); /* This lets IE know to call the script on all elements which get the 'box' class */
} Copy Code
最近用到了这个东西,发现动态改变div的内容之后,这段脚本生成的vml会出现变形。。
所以加了一个手动刷新的函数,通过innerHTML赋值之后调用一下就可以了
el.innerHTML = '....';
if(window.update_css3_fix) update_css3_fix(el);
Copy Code
如果使用jquery就不用这么麻烦,在你的框架里加一段
(function()
{
if (!jQuery.browser.msie) return;
jQuery.fn.__ohtml__ = jQuery.fn.html;
jQuery.fn.html = function(value)
{
jQuery(this).__ohtml__(value);
this.each(function()
{
update_css3_fix(this);
});
return this;
};
})(); Copy Code
另外官网下载的脚本还会产生yourdomain/none的404请求,也已经修复
修改之后的文件ie-css3.htc
很简单的例子
//计数加一
count ++
//更新ui
jQuery('#count').text(count); Copy Code
相信几乎所有前端工程师都会写过上面这样的代码,更新数据,然后更新ui,行云流水般的。 然而也是相当一部分内测bug的起源,数据删除了,ui里的计数没有变,或者ui变了,数据里确没有删除。而在逻辑复杂的应用里,更是很难保证不出这种低级错误。
其实我们可以通过自定义事件,这样重写
this.data_bind('count', 'change', function(count)
{
//更新计数
jQuery('#count').text(count);
});
....
this.data_bind('count', 'change', function(count)
{
//刷新分页
refresh_pager(count);
});
this.set_data('count', this.get_data('count') + 1); Copy Code
上次D2上听金大为讲模板技术,当时感觉耳目一新,最近边写边考虑这些新思想,其实使用现有的自定义事件要简单的多,而且灵活性,适用性更好。
用过flex的同学看完这篇文章肯定会说:靠,你们写js的还真是原始社会。。
一个简单的load动作,如果简单用任何一个js框架实现
startloding();
new ajax({
url : 'test.php',
compete : function()
{
stoploading()
},
success : function(data)
{
try
{
var obj = json_decode(data);
}
catch(e)
{
//服务异常,未返回json造成异常
error('服务器异常');
return;
}
//正常的业务逻辑错误
if ( json['code'] !== 0 )
{
error(json['desc']);
return;
}
...
},
error : function()
{
//网络请求失败造成异常
error('网络异常');
}
}); Copy Code
而一个业务框架对ajax再次包装,成为一个action
new action({
action : 'load',
action_name : '加载',
url : 'test.php'
});
api.add_action('load_start', startloading);
api.add_action('load_complete', stoploading);
//这里的成功不是ajax成功,而是判定json['code']之后action真正的成功,这就要求所有action需要有统一的成功判定标准,和json包装格式
api.add_action('load_success', function(msg, data){ .... });
//这里没有添加异常处理,因为没有特殊需要,所以action会执行默认的错误处理,可能是一个弹窗 Copy Code
不仅仅是节省了代码,后者有更好的可读性,load动作本身也具有了更好的重用性
具体的框架代码已经在用,还不是很完美,待贴~
做web这么长时间,感觉最恶心的就是表单验证这块了,很无聊,很烦琐,也很重要..
这个验证类的功能参考了codeigniter的表单验证库的功能,按照我的想法实现完毕又去对照codeigniter的代码,感觉还是我的这个比较灵活实用
…
/**
* 表单验证类
* Author : emptyhua@gmail.com
* Version : beta
*/
class FormValidator
{
//所有验证函数定义时的前缀
const PREFIX = 'form_validator_';
//存储验证函数的出错信息
public static $error_messages = array();
//存储验证相关的数据
protected $valid_rules = array();
//存储上次验证的出错信息
protected $errors = array();
//是否完全检查
protected $complete_check = true;
public static function set_error($rule, $error)
{
self::$error_messages[$rule] = $error;
}
/**
* 遇到第一个错误便返回
*/
public function first_error_only()
{
$this->complete_check = false;
}
/**
* 执行所有验证规则,收集所有错误
*/
public function show_all_errors()
{
$this->complete_check = true;
}
/**
* 设置验证规则
* @param string $var 验证的变量名,例如 username
* @param string $var_name 变量名的描述,例如 用户名
* @param string $func_name 验证规则,可以是多个,并且可以传参,例如 require|length(9,12)
* @param string $error_message 自定义的出错信息,可选,如果给定将覆盖验证函数的默认出错信息
*/
public function set_rules($var, $var_name, $func_name, $error_message = NULL)
{
$data = array();
$data['var_name'] = $var_name;
$data['error'] = $error_message;
$data['funcs'] = array();
$funcs_with_arg = explode('|', $func_name);
$args_match = array();
//解析验证规则
foreach( $funcs_with_arg as $func_with_arg )
{
preg_match('/\((.*)\)$/', $func_with_arg, $args_match);
//规则函数是否携带参数
if ( count($args_match) > 0 )
{
//参数列表
$args = explode(',', $args_match[1]);
//去掉参数后的验证规则名
$func = str_replace('(' . $args_match[1] . ')', '', $func_with_arg);
$data['funcs'][$func] = $args;
}
else
{
$data['funcs'][$func_with_arg] = NULL;
}
}
$this->valid_rules[$var] = $data;
}
/**
* 检验一组数据是否合法
* @param array $data 一个关联数组
* @return boolean
*/
public function is_valid($data)
{
$this->errors = array();
$valid = true;
//遍历的顺序为规则添加的顺序
foreach( $this->valid_rules as $var => $rule )
{
//判断数据中是否有此字段,没有的话置一个空的
if (!isset($data[$var]))
$data[$var] = '';
foreach($rule['funcs'] as $func => $args)
{
//真实的验证函数的名称,例如 form_validator_require
$func_run = self::PREFIX . $func;
//如果函数未定义,循环继续
if ( !is_callable($func_run) ) continue;
//为验证函数组装参数
//顺序为:当前验证字段的值, 所有验证数据, 验证规则参数1, ...
if ( $args === NULL )
{
$args = array($data[$var], $data);
}
else
{
array_unshift($args, $data);
array_unshift($args, $data[$var]);
}
//调用验证函数
if ( !call_user_func_array($func_run, $args) )
{
$valid = false;
//如果set_rules的时候没有自定义错误信息,则使用默认出错信息
if ( $rule['error'] === NULL )
{
//使用sprintf拼接错误信息
//参数顺序: 验证字段的描述, 验证函数的参数1, 验证函数的参数2 ...
//去掉刚才添加的字段值
array_shift($args);
//去掉刚才添加的所有验证数据
array_shift($args);
//添加字段名的描述
array_unshift($args, $rule['var_name']);
//添加默认的出错信息
array_unshift($args, self::$error_messages[$func]);
$this->errors[] = call_user_func_array('sprintf', $args);
}
else
{
//使用自定义错误信息
$this->errors[] = $rule['error'];
continue 2;
}
//如果设置不进行完全检查,则发现第一个错误后跳出最外层循环
if ( !$this->complete_check )
{
break 2;
}
}
}
}
return $valid;
}
/**
* 获取出错信息
* @return string array
*/
public function get_errors()
{
return $this->errors;
}
/**
* 返回第一条出错信息
* @return string
*/
public function get_first_error()
{
return $this->errors[0];
}
}
//扩展验证规则很方便~
//设置规则的默认出错信息
FormValidator::set_error('require', '%s不能为空');
//定义验证函数,以FormValidator::PREFIX打头
function form_validator_require($str)
{
return !(trim($str) == '');
}
FormValidator::set_error('equal', '重复输入不一致');
function form_validator_equal($str, $data, $eqto)
{
if ( !isset($data[$eqto]) )
{
return false;
}
return $data[$eqto] == $str;
} Copy Code
使用方法
$vd = new FormValidator();
$vd->set_rules('p', '密码', 'require|length(9,12)');
$vd->set_rules('p2', '密码验证', 'equa(p)', '两次密码输入不一致');
if (!$vd->is_valid($_POST))
{
var_dump($vd->get_errors());
} Copy Code