视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
JavaScript输入邮箱自动提示实例代码_javascript技巧
2020-11-27 21:18:42 责编:小采
文档
本来想把之前对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); // 渲染出字符串

例子:

代码如下:





ice demo

输出的代码片断

"
}
});
console.log(html);
$("#content").html(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);

下载本文
显示全文
专题