林秀栋的技术博客

设计模式(三十二) Widget模式

从三十二开始的设计模式属于架构型设计模式

//将页面分解为部件,针对部件开发,最终组合为完整页面

//处理数据-》获取模板-》处理模板-》编译执行

//模块调用,调用简单模板模式中的模块
F.module("lib/template",function(){
    //模板引擎,处理数据和编译模板入口
    var _TplEngine=function(str,data){
        if(data instanceof Array){	//如果是数组
            var html = '',	//缓存渲染模板结果
               i = 0,
               len = data.length;
            for(; i < len; i++){
                html += _getTpl(str)(data[i]);
                //缓存模板渲染结果,也可写成html += arguments.callee(str, data[i]);
            }
            return html;
        }else{
            return _getTpl(str)(data);
        }
    },
    //获取模板,str:模板容器id,或者模板字符串
    _getTpl=function(str){
        var ele = document.getElementById(str);
        if(ele){
            var html = /^(textarea|input)$/i.test(ele.nodeName) ? ele.value : ele.innerHTML;
            return _compileTpl(html);
        }else{
            return _compileTpl(str);
        }
    },
    //处理模板
    //模板<a> \{\%=test\%\}</a>
    //转为template_array.push(‘<a>’,typeof(test)===’undefined’?”:test,’</a>’);
    _dealTpl=function(str){
        var _left = ' \{\%',
            _right = '\%\}';
        return String(str)
                .replace(/&lt;/g, '<')	//转义'<'
                .replace(/&gt;/g, '>')	//转义'>'
                .replace(/[\r\t\n]/g, '')	//过滤回车符,制表符,回车符
                //替换内容
                .replace(new RegExp(_left+'=(.*?)'+_right,'g'), "',typeof($1)==='undefined'?'':$1,'")
                .replace(new RegExp(_left,'g'), "');")	//替换左分隔符
                .replace(new RegExp(_right,'g'), "template_array.push('");	//替换右分隔符
    },
    //编译执行
    _compileTpl=function(str){
        var fnBody = "…";
        return new Function("templateData", fnBody)
    },
})

//上文fnBody中是字符串,下面把字符串分行解析
var template_array=[];\n
var fn = (function(data){ \n
    var template_key = ''; \n	//渲染数据变量的执行函数体
    for(key in data){ \n
        //为渲染数据变量的执行函数体增加赋值语句
        template_key+=(‘var '+key+'=data[\"'+key+'\"];'); \n
    }\n
    //执行渲染数据变量的执行函数体
    eval(template_key); \n
    //为模板容器组添加成员(此时渲染数据将替换容器中的变量)
    template_array.push('"+_dealTpl(str)+"'); \n
    //释放渲染数据变量函数
    template_key = null; \n
})(templateData); \n
fn = null; \n	//释放闭包
return template_array.join('');

//使用
<script type="text/template" id="a">
    <div>
         \{\% for(var i = 0; i < tagCloud.length; i++){
            var ctx = tagCloud[i]; \%\}
            <a href="#" title=" \{\%=ctx["title"]\%\}"> \{\%=ctx["text"]\%\}</a>
         \{\% } \%\}
    </div>
</script>
var data = {
    tagCloud:[
        {title: 1, text: 't1'},
        {title: 2, text: 't2'}
    ]
}
F.module(['lib/template'],function(template){
    var str = template('a', data);
    dom.html('test', str)
})