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 相关文章推荐
JavaScript DOM 学习第三章 内容表格
Feb 19 Javascript
关于js注册事件的常用方法
Apr 03 Javascript
JavaScript设置首页和收藏页面的小例子
Nov 11 Javascript
js抽奖实现随机抽奖代码效果
Dec 02 Javascript
jQuery中对未来的元素绑定事件用bind、live or on
Apr 17 Javascript
EasyUI修改DateBox和DateTimeBox的默认日期格式示例
Jan 18 Javascript
原生js实现图片放大缩小计时器效果
Jan 20 Javascript
详解使用angular框架离线你的应用(pwa指南)
Jan 31 Javascript
vue计算属性computed的使用方法示例
Mar 13 Javascript
解决layui 三级联动下拉框更新时回显的问题
Sep 03 Javascript
详解小程序如何改变onLoad的执行时机
Nov 01 Javascript
js 数据类型判断的方法
Dec 03 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相当简单的分页类
2008/10/02 PHP
php自动加载机制的深入分析
2013/06/08 PHP
Symfony2实现在controller中获取url的方法
2016/03/18 PHP
php正则去除网页中所有的html,js,css,注释的实现方法
2016/11/03 PHP
在一个浏览器里呈现所有浏览器测试结果的前端测试工具的思路
2010/03/02 Javascript
用jquery与css打造个性化的单选框和复选框
2010/10/20 Javascript
js点击更换背景颜色或图片的实例代码
2013/06/25 Javascript
js浮动图片的动态效果
2013/07/10 Javascript
Jquery 跨域访问 Lightswitch OData Service的方法
2013/09/11 Javascript
$(document).ready(function() {})不执行初始化脚本
2014/06/19 Javascript
JS按回车键实现登录的方法
2014/08/25 Javascript
自定义刻度jQuery进度条及插件
2015/09/02 Javascript
jQuery中的基本选择器用法学习教程
2016/04/14 Javascript
javascript判断图片是否加载完成的方法推荐
2016/05/13 Javascript
浅谈js继承的实现及公有、私有、静态方法的书写
2016/10/28 Javascript
微信小程序实战之运维小项目
2017/01/17 Javascript
JavaScript中动态向表格添加数据
2017/01/24 Javascript
node.js平台下的mysql数据库配置及连接
2017/03/31 Javascript
vue移动端裁剪图片结合插件Cropper的使用实例代码
2017/07/10 Javascript
JS中appendChild追加子节点无效的解决方法
2018/10/14 Javascript
Python列表(list)常用操作方法小结
2015/02/02 Python
深入解析Python中的上下文管理器
2016/06/28 Python
VPS CENTOS 上配置python,mysql,nginx,uwsgi,django的方法详解
2019/07/01 Python
python selenium 查找隐藏元素 自动播放视频功能
2019/07/24 Python
pytorch进行上采样的种类实例
2020/02/18 Python
python3中sorted函数里cmp参数改变详解
2020/03/12 Python
基于python图书馆管理系统设计实例详解
2020/08/05 Python
无需JS和jQuery代码实现CSS3鼠标浮动放大图片
2016/11/21 HTML / CSS
一篇文章带你学习CSS3图片边框
2020/11/04 HTML / CSS
美国婚戒购物网站:Anjays Designs
2017/06/28 全球购物
Madewell澳大利亚官方网站:美国休闲服饰品牌
2019/07/18 全球购物
领班岗位职责范文
2014/02/06 职场文书
志愿者活动总结报告
2014/06/27 职场文书
安全月宣传标语
2014/10/07 职场文书
病人慰问信范文
2015/02/15 职场文书
承诺书应该怎么写?
2019/09/10 职场文书