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

underscore模版引擎的工作原理入门 #5

Open
iscarecrow opened this issue Dec 18, 2016 · 0 comments
Open

underscore模版引擎的工作原理入门 #5

iscarecrow opened this issue Dec 18, 2016 · 0 comments

Comments

@iscarecrow
Copy link
Owner

iscarecrow commented Dec 18, 2016

  • 如何通过正则替换和函数执行实现简单的templateEngine
  • underscore如何实现
  • QA

如何通过正则替换和函数执行实现简单的

采用 innerHTML 写入带html标签的string

方案
  • 正则方案
  • 函数方案
思路

匹配出模版变量类似(<%=name%>) 替换成数据

正则方法 demo
var template = '<p>Hello, my name is <%name%>. I\'m <%age%> years old.</p>';
// 正则  <%age%> -> data.age
正则的问题
  • 嵌套数据
  • 循环逻辑
  • 判断逻辑
函数方法

思路 通过正则匹配,替换(<%=name%>)成变量,输出一个可执行函数。函数执行时写入变量。

不断的切片过程 string + val + string ...

嵌套数据 demo2

data={name:"jhon",profile:{age:12}}
function a(){
  return "<p>Hello, my name is "+ this.name + ". I\'m "+ this.profile.age +"years old.</p>";
}

function a(){
  var r=[];
  r.push("<p>Hello, my name is ");
  r.push(this.name);
  r.push(". I'm ");
  r.push(this.profile.age);
  r.push(" years old.</p>");
  return r.join("");
}
a.call({name:'jshn',profile:{age:12}});

带有逻辑for while if else demo3

function a() {
  var r=[];
  r.push("My skills:");
  if(this.showSkills) {
    for(var index in this.skills) {
      r.push("<li>");
      r.push(this.skills[index]);
      r.push("</li>");
    }
  } else {
    r.push("<p>none</p>");
  }
  return r.join("");
}
var data = {
  skills: ['hkhk','wewe','eeee'],
  showSkills: true
};
a.call(data)

以上参考http://krasimirtsonev.com/blog/article/Javascript-template-engine-in-just-20-line, 有了基本概念,我们再来看underscore的实现

underscore如何实现

实际的原理,就是通过+拼接字符串的一个可执行函数。_.template(tpl)第一步compile的过程返回了可执行的fn。填充数据只是给fn绑定上下文。完成调用。
通过正则,不断区分出String 和 模版自定义填充的变量<%= name%>。替换

function b(obj) {
  with(obj||{}) {
    return 'hello ' + word;
  }
}
b.call(null,{word:'world'});

简单变量

var tpl = _.template("<h1>Some text: <%= foo %></h1><h2><%= age %></h2>");
var x = tpl({foo: "blahblah",age:222});

function a(obj){
  var __t,__p = '',
      __j = Array.prototype.join,
      print = function(){
        __p += __j.call(arguments,'');
      };
  with(obj||{}){
        __p += '<h1>Some text: ' +
        ((__t = (foo)) == null ? '' : __t) +
        '</h1><h2>' +
        ((__t = (age)) == null ? '' : __t) +
        '</h2>';  }
 return __p;}

带逻辑

var t2 = _.template(
      "Users: <%_.forEach(users, function (u) {%>" + "<%=u%>, "+ "<%})%>"
  );
  var y = t2({ users: [ "Huey", "Dewey", "Louie" ]});
 
function c(obj) {
  var __t, __p = '',
    __j = Array.prototype.join,
    print = function() {
      __p += __j.call(arguments, '');
    };

  with(obj || {}) {
    __p += 'Users: ';
    _.forEach(users, function(u) {
      __p += '' +
        ((__t = (u)) == null ? '' : __t) +
        ', ';
    })
    __p += '';
  }
  return __p;
}

总结:通过上面的例子可以发现,underscore的模版引擎是将整段的htmlString,重新写入到dom当中。(不是很经济呐)

QA

  • 大面积的替换dom效率是否低下,是否应改变方案
  • 如何优化template Compile内容的写法
  • render完成后,是否添加一个finish的hook更好
  • 例如handlebar的register的方法如何实现

参考资料

@iscarecrow iscarecrow changed the title 前端http请求缓存小记 error Dec 18, 2016
@iscarecrow iscarecrow reopened this Jan 14, 2017
@iscarecrow iscarecrow changed the title error underscore模版引擎的工作原理入门 Jan 14, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant