JavaScript输入邮箱自动提示实例代码


Posted in Javascript onJanuary 13, 2014

本来想把之前对artTemplate源码解析的注释放上来分享下,不过隔了一年,找不到了,只好把当时分析模板引擎原理后,自己尝试

写下的模板引擎与大家分享下,留个纪念,记得当时还对比了好几个模板引擎来着。

这里所说的js的模板引擎,用的是原生的javascript语法,所以很类似php的原生模板引擎。

 

前端模板引擎的作用?

1. 可以让前端开发更简单,不需要为了生成一个dom结构而使用+运算符去拼接字符串,而只需要一个元素的(里面的html模板),或者一个变量(存储着模板),或者

一个模板文件

2. 易于维护,减少耦合,假使你的dom结构变化了,不需要更改逻辑代码,而只需要更改对应的模板(文件)

3. 可以缓存,如果你的模板是一个类似.tpl的文件,那么完全可以用浏览器去加载,并且还存下来。说到.tpl文件,可以做的不仅仅是缓存了,你还可以做到通过模块加载器

    将.tpl作为一个模块,那就可以按需加载文件,不是更省宽带,加快页面速度吗?

4. 等等等

 

前端模板引擎的原理?

原理很简单就是 对象(数据)+ 模板(含有变量) -> 字符串(html)

 

前端模板引擎的如何实现?

通过解析模板,根据词法,将模板转换成一个函数,然后通过调用该函数,并传递对象(数据),输出字符串(html)

(当然,具体的还要看代码的)

就像这样:

var tpl = 'i am <%= name%>, <%= age=> years old'; // <%=xxx>% 词法,标记为变量var obj = {
    name : 'lovesueee' ,
    age : 24
};
var fn = Engine.compile(tpl); // 编译成函数
var str = fn(obj);   // 渲染出字符串       

例子:

<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>ice demo</title>
<script src="/javascripts/jquery/jquery-1.7.2.js"></script>
<script src="/javascripts/ice/ice.js"></script>
<body>
    <div id="content"></div>
</body>
<script type="text/html" id="tpl">
    <div>here is the render result:</div>
    <%  = this.title() ;%>
    <table border=1>
    <% for(var i=0,tl = this.trs.length,tr;i<tl;i++){  %>
        <%
            tr = this.trs[i];
            if (tr.sex === "女") {
        %>
        <tr>
        <td><%= tr.name;; %></td> <td><%= tr.age; %></td> <td><%= tr.sex || "男" %></td>
        </tr>
        <% } %>
    <% } %>
    </table>
    <img src="<%= this.href %>">
    <%= this.include('tpl2',this); %>
</script>
<script type="text/html" id="tpl2">
    <div>here is the render result:</div>
    <%  = this.print('Welcome to Ice Template') ;%>
    <table border=1>
    <% for(var i=0,tl = this.trs.length,tr;i<tl;i++){  %>
        <%
            tr = this.trs[i];
            if (tr.sex === "男") {
        %>
        <tr>
        <td><%= tr.name;; %></td> <td><%= tr.age; %></td> <td><%= tr.sex || "男" %></td>
        </tr>
        <% } %>
    <% } %>
    </table>
    <img src="<%= this.href %>">
</script>
<script>
    var trs = [
        {name:"隐形杀手",age:29,sex:"男"},
        {name:"索拉",age:22,sex:"男"},
        {name:"fesyo",age:23,sex:"女"},
        {name:"恋妖壶",age:18,sex:"男"},
        {name:"?崎",age:25,sex:"男"},
        {name:"你不懂的",age:30,sex:"女"}
    ]
    // var html = ice("tpl",{
    //     trs: trs,
    //     href: "http://images.3water.com/type4.jpg"
    // },{
    //     title: function(){
    //         return "<p>这是使用视图helper输出的代码片断</p>"
    //     }
    // });
    var elem = document.getElementById('tpl');
    var tpl = elem.innerHTML;
    var html = ice(tpl,{
        trs: trs,
        href: "http://images.3water.com/type4.jpg"
    },{
        title: function(){
            return "<p>这是使用视图helper输出的代码片断</p>"
        }
    });
    console.log(html);
    $("#content").html(html);
</script>
</html>

简单的实现:

(function (win) {
    // 模板引擎路由函数
    var ice = function (id, content) {
        return ice[
            typeof content === 'object' ? 'render' : 'compile'
        ].apply(ice, arguments);
    };

    ice.version = '1.0.0';
    // 模板配置
    var iConfig = {
        openTag  : '<%',
        closeTag : '%>'
    };

    var isNewEngine = !!String.prototype.trim;
    // 模板缓存
    var iCache = ice.cache = {};
    // 辅助函数
    var iHelper = {
        include : function (id, data) {
            return iRender(id, data);
        },
        print : function (str) {
            return str;
        }
    };
    // 原型继承
    var iExtend = Object.create || function (object) {
        function Fn () {};
        Fn.prototype = object;
        return new Fn;
    };
    // 模板编译
    var iCompile = ice.compile = function (id, tpl, options) {
        var cache = null;
        id && (cache = iCache[id]);
        if (cache) {
            return cache;
        }
        // [id | tpl]
        if (typeof tpl !== 'string') {
            var elem = document.getElementById(id);
            options = tpl;
            if (elem) {
                // [id, options]
                options = tpl;
                tpl = elem.value || elem.innerHTML;
            } else {
                //[tpl, options]
                tpl = id;
                id = null;
            }
        }
        options = options || {};
        var render  = iParse(tpl, options);
        id && (iCache[id] = render);
        return render;
    };

    // 模板渲染
    var iRender = ice.render = function (id, data, options) {
        return iCompile(id, options)(data);
    };

    var iForEach = Array.prototype.forEach ?
        function(arr, fn) {
            arr.forEach(fn)
        } :
        function(arr, fn) {
            for (var i = 0; i < arr.length; i++) {
                fn(arr[i], i, arr)
            }
        };

    // 模板解析
    var iParse = function (tpl, options) {
        var html = [];
        var js = [];
        var openTag = options.openTag || iConfig['openTag'];
        var closeTag = options.closeTag || iConfig['closeTag'];
        // 根据浏览器采取不同的拼接字符串策略
        var replaces = isNewEngine
            ?["var out='',line=1;", "out+=", ";", "out+=html[", "];", "this.result=out;"]
            : ["var out=[],line=1;",  "out.push(", ");", "out.push(html[", "]);", "this.result=out.join('');"];
        // 函数体
        var body = replaces[0];
        iForEach(tpl.split(openTag), function(val, i) {
            if (!val) {
                return;
            }
            var parts = val.split(closeTag);
            var head = parts[0];
            var foot = parts[1];
            var len = parts.length;
            // html
            if (len === 1) {
                body += replaces[3] + html.length + replaces[4];
                html.push(head);
            } else {
                if (head ) {
                    // code
                    // 去除空格
                    head = head
                        .replace(/^\s+|\s+$/g, '')
                        .replace(/[\n\r]+\s*/, '')

                    // 输出语句
                    if (head.indexOf('=') === 0) {
                        head = head.substring(1).replace(/^[\s]+|[\s;]+$/g, '');
                        body += replaces[1] + head + replaces[2];
                    } else {
                        body += head;
                    }
                    body += 'line+=1;';
                    js.push(head);
                }
                // html
                if (foot) {
                    _foot = foot.replace(/^[\n\r]+\s*/g, '');
                    if (!_foot) {
                        return;
                    }
                    body += replaces[3] + html.length + replaces[4];
                    html.push(foot);
                }
            }
        });
        body = "var Render=function(data){ice.mix(this, data);try{"
            + body
            + replaces[5]
            + "}catch(e){ice.log('rend error : ', line, 'line');ice.log('invalid statement : ', js[line-1]);throw e;}};"
            + "var proto=Render.prototype=iExtend(iHelper);"
            + "ice.mix(proto, options);"
            + "return function(data){return new Render(data).result;};";
        var render = new Function('html', 'js', 'iExtend', 'iHelper', 'options', body);
        return render(html, js, iExtend, iHelper, options);
    };
    ice.log = function () {
        if (typeof console === 'undefined') {
            return;
        }
        var args = Array.prototype.slice.call(arguments);
        console.log.apply && console.log.apply(console, args);
    };
    // 合并对象
    ice.mix = function (target, source) {
        for (var key in source) {
            if (source.hasOwnProperty(key)) {
                target[key] = source[key];
            }
        }
    };
    // 注册函数
    ice.on = function (name, fn) {
        iHelper[name] = fn;
    };
    // 清除缓存
    ice.clearCache = function () {
        iCache = {};
    };
    // 更改配置
    ice.set = function (name, value) {
        iConfig[name] = value;
    };
    // 暴露接口
    if (typeof module !== 'undefined' && module.exports) {
        module.exports = template;
    } else {
        win.ice = ice;
    }
})(window);
Javascript 相关文章推荐
js日历功能对象
Jan 12 Javascript
jQuery javaScript捕获回车事件(示例代码)
Nov 07 Javascript
多个jquery.datatable共存,checkbox全选异常的快速解决方法
Dec 10 Javascript
浅谈JSON和JSONP区别及jQuery的ajax jsonp的使用
Nov 23 Javascript
jQuery基于muipicker实现仿ios时间选择
Feb 22 Javascript
JavaScript 函数节流详解及方法总结
Feb 09 Javascript
详谈jQuery.load()和Jsp的include的区别
Apr 12 jQuery
Vue.js子组件向父组件通信的方法实例代码详解
Dec 10 Javascript
node(koa2) web应用模块介绍详解
Mar 29 Javascript
Vue.js实现tab切换效果
Jul 24 Javascript
javascript实现拼图游戏
Jan 29 Javascript
JavaScript小技巧带你提升你的代码技能
Sep 15 Javascript
js判断是否为ie的方法小结
Jan 13 #Javascript
jquery教程限制文本框只能输入数字和小数点示例分享
Jan 13 #Javascript
javascript教程之不完整的继承(js原型链)
Jan 13 #Javascript
javascript函数作用域学习示例(js作用域)
Jan 13 #Javascript
多选列表框动态添加,移动,删除,全选等操作的简单实例
Jan 13 #Javascript
鼠标经过tr时,改变tr当前背景颜色
Jan 13 #Javascript
js导航栏单击事件背景变换示例代码
Jan 13 #Javascript
You might like
用PHP即时捕捉PHP中的错误并发送email通知的实现代码
2013/01/19 PHP
ThinkPHP结合AjaxFileUploader实现无刷新文件上传的方法
2014/10/29 PHP
关于js遍历表格的实例
2013/07/10 Javascript
javascript检查表单数据是否改变的方法
2013/07/30 Javascript
得到form下的所有的input的js代码
2013/11/07 Javascript
JS判断移动端访问设备并加载对应CSS样式
2014/06/13 Javascript
基于javascript实现彩票随机数生成(升级版)
2020/04/17 Javascript
js+css3制作时钟特效
2016/10/16 Javascript
js/jq仿window文件夹框选操作插件
2017/03/08 Javascript
layui中layer前端组件实现图片显示功能的方法分析
2017/10/13 Javascript
详解基于 Nuxt 的 Vue.js 服务端渲染实践
2017/10/24 Javascript
vue中关闭eslint的方法分析
2018/08/04 Javascript
JS跨域请求的问题解析
2018/12/03 Javascript
微信小程序实现元素渐入渐出动画效果封装方法
2019/05/18 Javascript
node.JS路径解析之PATH模块使用方法详解
2020/02/06 Javascript
vue深度监听(监听对象和数组的改变)与立即执行监听实例
2020/09/04 Javascript
VUE-ElementUI 自定义Loading图操作
2020/11/11 Javascript
[02:16]卖萌的僵尸 DOTA2神话信使飞僵小宝来袭
2014/03/24 DOTA
[07:49]2014DOTA2国际邀请赛 Newbee夺冠后采访xiao8坦言奖金会上交
2014/07/23 DOTA
[02:11]2016国际邀请赛中国区预选赛最美TA采访现场玩家
2016/06/28 DOTA
Python实现拷贝多个文件到同一目录的方法
2016/09/19 Python
python3使用requests模块爬取页面内容的实战演练
2017/09/25 Python
Python完成毫秒级抢淘宝大单功能
2019/06/06 Python
Python如何在单元测试中给对象打补丁
2020/08/03 Python
CSS3实现跳动的动画效果
2016/09/12 HTML / CSS
HTML5页面嵌入小程序没有返回按钮及返回页面空白的问题
2020/05/28 HTML / CSS
教师自我评价范例
2013/09/24 职场文书
2014年小班元旦活动方案
2014/02/16 职场文书
体育教学随笔感言
2014/02/24 职场文书
广告语设计及教案
2014/03/21 职场文书
电子信息工程专业求职信
2014/06/28 职场文书
见习报告格式要求
2014/11/04 职场文书
2015年度质量工作总结报告
2015/04/27 职场文书
毕业生爱心捐书倡议书
2015/04/27 职场文书
PostgreSQL将数据加载到buffer cache中操作方法
2021/04/16 PostgreSQL
解析MySQL binlog
2021/06/11 MySQL