Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

前端模板实现 #5

Open
andyChenAn opened this issue Jul 31, 2018 · 0 comments
Open

前端模板实现 #5

andyChenAn opened this issue Jul 31, 2018 · 0 comments
Labels
javascript javascript

Comments

@andyChenAn
Copy link
Owner

andyChenAn commented Jul 31, 2018

前端模板

前端模板引擎有很多,大部分都是大同小异,我们经常看到通过字符串来拼接很长的一端html代码,里面有html代码,有js代码。这样完全将html和js代码耦合在一起。

前端模板引擎原理:

通过前端模板函数将模板中的html代码和js语句、变量分离,然后通过Function构造函数来动态生成具有数据性的html代码。

具体代码实现:

function template (tpl , data) {
	var result = 'var arr = [];';
    var splitSymbol = '|';
	var str = tpl
		.replace(/(<[^%]+>)/g , "arr.push('$1')" + splitSymbol)
		.replace(/<%?=(\s*.+)%>/g , "arr.push($1)" + splitSymbol)
                .replace(/<%(\s*.+)%>/g , '$1' + splitSymbol)
	result = result + str;
	result  += 'return arr.join("")';
	result = result.split('|');
	result = result.map(function (item) {
		return item.replace(/\n/g , '');
	});
    return new Function('data' , result.join('\n'))(data);
};

上面的模板引擎函数,我们最后使用的是

new Function('data' , result.join('\n'))(data);

这样我们的字符串模板里面必须使用的是data对象,而不能使用其他名称,当然我们也可以稍微的改造一下,通过调用函数的apply方法来改变this的指向。

var fn = new Function('data' , result.join('\n'));
return fn.apply(data);

字符串模板是这样的:

<script type="text/html" id="tpl">
	<% if (this.show) { %>
		<span><%= this.name %></span>
	<% } else { %>
		<span><%= this.age %></span>
    <% } %>
    <% for (var i = 0 ; i < this.list.length ; i++) { %>
        <% if (this.list[i] >= 2) { %>
			<span><%= this.list[i] %></span>
			<div>sdfdsfdgdsg</div>
			<p>sdf</p>
        <% } else { %>
            <div style="color:#f00;"><%= this.list[i] %></div>
        <% } %>
	<% } %>
	<span>asdlfjas</span>
</script>

对于JavaScript语句,我们将语句放在"<% javascript语句 %>"中,而对于JavaScript值,我们放在"<%= 值 %>"中。

例子:

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>Document</title>
</head>
<body>
<div id="box"></div>
<script type="text/html" id="tpl">
	<% if (this.show) { %>
		<span><%= this.name %></span>
	<% } else { %>
		<span><%= this.age %></span>
    <% } %>
    <% for (var i = 0 ; i < this.list.length ; i++) { %>
        <% if (this.list[i] >= 2) { %>
			<span><%= this.list[i] %></span>
			<div>sdfdsfdgdsg</div>
			<p>sdf</p>
        <% } else { %>
            <div style="color:#f00;"><%= this.list[i] %></div>
        <% } %>
	<% } %>
	<span>asdlfjas</span>
</script>
<script>
var str = document.getElementById('tpl').innerHTML;
var obj = {
	show : false,
	name : 'andy',
	age : 22,
	address : '广州1',
    list : [1,2,3,4]
};
function template (tpl , data) {
	var result = 'var arr = [];';
    var splitSymbol = '|';
	var str = tpl
		.replace(/(<[^%]+>)/g , "arr.push('$1')" + splitSymbol)
		.replace(/<%?=(\s*.+)%>/g , "arr.push($1)" + splitSymbol)
                .replace(/<%(\s*.+)%>/g , '$1' + splitSymbol)
	result = result + str;
	result  += 'return arr.join("")';
	result = result.split('|');
	result = result.map(function (item) {
		return item.replace(/\n/g , '');
	});
	var fn = new Function('data' , result.join('\n'));
	return fn.apply(data);
};
var s = template(str , obj);
var box = document.getElementById('box');
box.innerHTML = s;
</script>
</body>
</html>

注意:

1、html代码注释的头部和尾部只能在一行当中,如果不在一行,那么模板渲染会出错。

3、html模板中的如果需要使用引号(比如写html标签属性),那么必须是双引号,不然会报错。

@andyChenAn andyChenAn added the javascript javascript label Jul 31, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
javascript javascript
Projects
None yet
Development

No branches or pull requests

1 participant