[ Content | Sidebar ]

Archives for web dev

js中简单实现数据和ui绑定

很简单的例子

//计数加一
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的还真是原始社会。。

js业务框架中对ajax的再次包装

一个简单的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动作本身也具有了更好的重用性

具体的框架代码已经在用,还不是很完美,待贴~

php的一个表单验证类

做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 

ubuntu上flex开发相关

最近项目需要用到flex, 于是我要学这个本不打算学的东西…

我的环境很简单 flex sdk 4.0 + vim

sdk的安装参考 : http://blog.minidx.com/2008/05/17/853.html

flex的Makefile参考 : http://www.mindlence.com/WP/?p=301

编写好Makefile之后,就可以在vim里通过:make命令编译当前项目

vim的as和mxml语法高亮: http://www.fireyang.com/blog/?p=115

最后是我自己加的自动补全的字典(从flex4的文档里扣出来的….)

"将字典文件放到相应的目录就可以了,这里是~/.vim/as3_dict.txt
au FileType actionscript call AddAS3Dict()
function AddAS3Dict()
    set dictionary-=~/.vim/as3_dict.txt dictionary+=~/.vim/as3_dict.txt
    set complete-=k complete+=k
endfunction
Copy Code 

字典文件下载 : as3_dict
这个字典有9K多行,应该够用了…

初学的一点感觉:
虽然actionscript3已经远离了js的语法,但仍然是事件驱动的,所以对熟悉js开发的同学来说,flex很容易上手. 另一点感受是我再也不用考虑狗屁浏览器兼容性了..

最最后最近阅文档无数的终极结果,我的第一个flex半成品 : http://bluehua.org/demo/avatar-editor/

发个套页面的辅助工具

2010.4.22 使用vim的同学可以这样

command -nargs=0 HTML2Array :call HTML2Array()
function HTML2Array()
    exe("'<,'>s/\"/\\\\\"/g")
    exe("'<,'>s/^/\"/")
    exe("'<,'>s/$/\",/")
    exe("'<,'>g/^\"[\\t ]*\",$/d")
endfunction
Copy Code 

先用=排版命令对html排版,然后选中,:HTML2Array就可以了
———————————————–
jser套的页面一般是这样的

var html = [
//....
"            <div  class=\"right\">\n",
"                <div>\n",
"                    <span>\n",
"                        <input name=\"a\" type=\"text\" />\n",
"                    </span>\n",
"                    <span>\n",
"                        <input name=\"b\" type=\"text\" />\n",
"                    </span>\n",
"                </div>\n",
"                <div>\n",
"                    <input name=\"c\" type=\"text\" />\n",
"                </div>\n",
"                <div>\n",
"                    <input name=\"d\" type=\"text\" />\n",
"                </div>\n",
"            </div>\n",
//....
].join('');
Copy Code 

以前偶都是一点一点手工拼接的,今天抽时间写了段python,可以辅助一下~

#可以生成上面形式的字符串
cat tmp.html | python html2js.py
#或者生成 "abcd" + 这种字符串拼接的形式
cat tmp.html | python html2js.py --string
Copy Code 

脚本下载 : html2js.0.1

测试环境: ubuntu 9.10 python 2.6.4