• template模板函数


    template模板

    一个简单的字符串模板

    	var template = (function() { 
    		var cache = {};
    		return function(obj, str) {
    			if (!typeof str === "string") {
    				return;
    			}
    			var compile = cache[str]
    			if (!cache[str]) {
    				var template = str.replace(/<%=s*([^%>]+)s*%>/g, function() {
    					var k = arguments[1]
    					var tm =  "';" + k  + " tmp+='"
    					console.log("tm", tm)
    					return tm;
    				})
    				.replace(/${s*([^}]+)s*}/g, function() {
    					var k = arguments[1]
    					var tm = "' +" + k+ "+'";
    					return tm;
    				})
    				template = "var tmp = ""; with(obj){tmp ='" + template + "';}return tmp;"
    				console.log("template", template)
    				compile = new Function("obj", template)
    			}
    			return compile(obj)
    		}
    	})()
    
    

    使用

    	var str = "" +
    	"<div> "+
    	"<ul> "+
    	"<%= for(var i=0;i < obj.length; i++) { %> "+
    	"<li>${obj[i].name}</li> "+
    	"<%= } %> "+
    	"</ul> "+
    	"</div> "
    
    	var obj = [
    		{name: "李飞1"},
    		{name: "李飞2"},
    		{name: "李飞3"},
    	];
    	
    	var html = template(obj, str);
    	//生成字符串:"<div> <ul>  <li>李飞1</li>  <li>李飞2</li>  <li>李飞3</li>  </ul> </div> "
    

    介绍

    1. template函数有两个参数,第一个是数据,第二个是字符串模板.

    2. 字符串模板的格式要求

      1. 要执行的js代码需要写在: <%= 这里 %> . 比如: <%= var a = ""; %>
      2. 从对象里拿的数据写在: ${ 这里 } . 比如: ${obj.name}
    3. 如果obj是对象的话,可以直接从对象里拿数据.比如:

      	var obj = {name: "李飞"};
      	var str = "hello, ${name}";
      	var html = template(obj, str);	
      	//html 为 "hello,"李飞
      
    4. 如果obj是数组的话,不能直接拿,需要把数组便利才能使用.

    原理分析

    简单来说就是,把js代码写在固定的格式中,用String.replace()方法,获取到js代码的字符串.
    然后拼成一个函数格式的字符串.再用new Function()用这个函数字符串生成一个函数,去处理
    模板里的字符串并返回

    知识点

    1. String.replace(参数1, 参数2)

      1. 参数1,可以是字符串也可以是正则表达式,如果是正则表示式.并且有全局匹配g的话,会替换所有的匹配项.如果此时参数2是函数,那么有多少个匹配项,函数就会执行杜少次
      2. 参数2,可以是字符串,也可以是回调函数.函数的返回值会替代匹配的字符串.而回调函数的参数是一般有四个.可以用arguments来拿;
        1. 第一个参数是正则匹配到的字符串
        2. 第二个参数是与正则表达式中子表达式相匹配的字符串.也就是正则中的括号()匹配到的字符串.也即是template函数中我们需要拼接的js字符串.
        3. 如果子表达式有2个,则这里是第二个.多个以此类推.如果子表达式没有了.这里是整个被匹配到的字符串所在的length.
        4. 完整的原始字符串;
      3. replace函数不改变源字符串.返回值是替换之后的结果
    2. new Function(参数1, 参数2, functionBody)

      1. Function函数的最后一个参数functionBody就是函数字符串.这里的字符串会被变成js代码成为函数体
      2. functionBody前面的参数都是最终函数的参数.
    3. with语句

      	var obj = {name: "lifei", age: 18};
      	with(obj) {
      		var a = name; // "lifei"
      		var age = age; // 18
      	}
      

      在with语句中可以用变量直接获取obj对象上的属性.就好像把window换成了obj一样.可以直接访问他的属性.用在template函数中可以让拼接的字符串更加的清晰.但是with语句执行缓慢.慎用.

    4. 用来匹配js代码的正则表达式: /<%=s([^%>]+)s%>/g

      1. g: 全局匹配
      2. <%= : 用"<%="开头
      3. s* : 不定数量的空格
      4. [^%>] : 除了"%>"以外的其他字符
      5. () : 子表达式

    详解

    因为有Function函数的存在.我们可以拼接一个函数字符串来生成函数.对源字符串进行处理.所以我们的主要问题就是用String.replace()拿到模板里的js代码.再和源字符串一起拼接成一个函数字符串.再用new Function()生成函数,处理字符串.生成最后的结果.
    
    比如:
    ```
    	var str = "<span>name</span>"
    	var obj = {name: "李飞"}
    ```
    这两个参数我们最后要生成的函数字符串是: 
    ```
    	"var tmp = ""; with(obj){tmp ='<span>name</span>';}return tmp;"
    ```
    
    ```
    var template = (function() { 
    	var cache = {};
    	return function(obj, str) {
    
    		//判断str
    		if (!typeof str === "string") {
    			return;
    		}
    
    		//懒加载
    		var compile = cache[str]
    		if (!cache[str]) {
    			var template = str.replace(/<%=s*([^%>]+)s*%>/g, function() {
    				
    				//arguments拿到正则中([^%>]+)匹配到的,js代码;
    				var k = arguments[1]
    
    				//拼接,这里最麻烦
    				var tm =  "';" + k  + " tmp+='"
    				return tm;
    			})
    
    			//因为js的执行代码和从对象中取数据的代码格式不一样.所以要匹配两次.
    			.replace(/${s*([^}]+)s*}/g, function() {
    				var k = arguments[1]
    				var tm = "' +" + k+ "+'";
    				return tm;
    			})
    
    			//拼接函数代码
    			template = "var tmp = ""; with(obj){tmp ='" + template + "';}return tmp;"
    			console.log("template")
    			//生成函数.
    			compile = new Function("obj", template)
    		}
    
    		//返回值
    		return compile(obj)
    	}
    })()
    
  • 相关阅读:
    第二章 Java浮点数精确计算
    第一章 Java代码执行流程
    第九章 JVM调优推荐
    第八章 JVM性能监控与故障处理工具(2)
    基于Redis构建10万+终端级的高性能部标JT808协议的Gps网关服务器(转)
    基于Java Netty框架构建高性能的Jt808协议的GPS服务器(转)
    Netty(七):流数据的传输处理
    Java中的位运算符
    二进制(原码、反码、补码)
    Java数据结构和算法(二):数组
  • 原文地址:https://www.cnblogs.com/bridge7839/p/8099019.html
Copyright © 2020-2023  润新知