The code should be written in a way that others cannot understand (19)

This article refers to the book "JavaScript Design Patterns"-Zhang Rongming

Article Directory

Preface

  Have you ever encountered a situation of operating a large number of nodes, for example, if we want to create a display area on the page, this area needs to display different structures with different options, then we need to operate different according to the options node. First create the node, then create the node content, insert the node content into the created node, and finally insert the node into the parent node.

  Under this set of operations, a node requires 4 steps. If there are more nodes, the performance consumption is a bit unbearable.

  In order to solve this problem, we can use a simple template method. If you have been exposed to template strings, it is easy to learn.

Simple template mode

  Piece together the view through the format string to avoid a lot of node operations when creating the view, and optimize the memory overhead .

  For example, we specify a display area container to display different information.

//命名空间 单体对象
var A = A || [];
//主体展示容器区
A.root = document.getElementById('container');
//创建视图方法集合
A.strategy = {
    
    
	'listPart': function() {
    
    },
	'codePart': function() {
    
    },
	'onlyTitle': function() {
    
    },
	'guide': function() {
    
    }
	//.......
}
//创建视图入口
A.init = function(data) {
    
    
	//根据传输的试图类型创建视图
	this.strategy[data.type](data);
}

  The next step is to implement each of the creation algorithms in the strategy . (The code below is just a glance)

//文字列表展示
'listPart': function(data) {
    
    
	var s = document.createElement('div'),          //模块容器
		h = document.createElement('h2'),           //标题容器
		p = document.createElement('p'),            //描述容器
		ht = document.createTextNode(data.data.h2), //标题内容
		pt = document.createTextNode(data.data.p),  //描述内容
		ul = document.createElement('ul'),          //列表容器
		ldata = data.data.li,                       //列表数据
		//li 列表项容器, strong 列表项标题,span 列表项解释,t 列表项标题内容, c 列表项解释内容
		li, strong, span, t, c;
	//有 id 设置模块 id
	data.id && (s.id = data.id);
	s.className = 'part'; //设置模块类名
	h.appendChild(ht);    //将标题内容放到标题容器
	p.appendChild(pt);    //将描述内容放到描述容器
	s.appendChild(h);     //将标题容器插入模块容器
	s.appendChild(p);     //将描述容器插入模板容器
	//遍历列表数据
	for(var i = 0, len = ldata.length; i < len; i++) {
    
    
		li = document.createElement('li');            //创建列表项容器
		strong = document.createElement('strong');    //创建列表项标题容器
		span = document.createElement('span');        //创建列表项解释容器
		t = document.createTextNode(ldata[i].strong); //创建列表项标题内容
		c = document.createTextNode(ldata[i].span);   //创建列表项解释内容
		strong.appendChild(t);       //向列表项标题容器中插入标题内容
		span.appendChild(c);         //向列表项解释容器中插入解释类容
		li.appendChild(strong);      //向列表项中插入列表项标题
		li.appendChild(span);        //向列表项中插入列表项解释
		ul.appendChild(li);          //向列表项中插入列表项
	}
	s.appendChild(ul);     //向模块中插入列表
	A.root.appendChild(s); //展现模块
}

  Do you think that the above code always looks serial when you read it. Although it is neat and tidy, it looks big. This is what we said at the beginning to operate various nodes. It’s hard to write, it’s hard to read, and it’s hard to run the browser.

  In order to solve the above problem, we can try to create a template, use data to format the string to render the view and insert it into the container. This will improve the performance of the solution a lot. First, we need a renderer, for example, if we want to use data Object '{demo:'this is a demo'}' to format '<a>{#demo#}</a>+' string template and get '<a>this is a demo</a>' rendering The latter template can be inserted into the page, but first, a formateString method is required to render the template engine. Replace {#demo#} in the string template with the demo attribute value in the data object .

//渲染模板方法
A.formateString = function(str, data) {
    
    
	return str.replace(/\{#(\w+)#\}/g, function(match, key) {
    
    return typeof data[key] === undefined ? '' : data[key]});
}

  With this method, we can render the view we need through a simple template.

//文字列表展示
'listPart': function(data) {
    
    
	var s = document.creatElement('div'),   //容器模块
		ul = '',                            //列表字符串
		ldata = data.data.li,               //列表数据
		//模块模板
		tpl = [
			'<h2>{#h2#}</h2>',
			'<p>{#p#}</p>',
			'<ul>{#ul#}</ul>'
		].join(''),
		//列表项模板
		liTpl = [
			'<li>',
				'<strong>{#strong#}</strong>',
				'<span>{#span#}</span>',
			'</li>'
		].join('');
	//有 id 设置模块 id
	data.id && (s.id = data.id);
	//遍历列表数据
	for(var i = 0, len = ldata.length; i < len; i++) {
    
    
		//如果有列表项数据
		if(ldata[i].em || ldata[i].span) {
    
    
			//列表字符串追加一项列表项
			ul += A.formateString(liTpl, ldata[i]);
		}
	}
	//装饰列表数据
	data.data.ul = ul;
	//渲染模块并插入模块中
	s.innerHTML = A.formateString(tpl, data.data);
	//渲染模块
	A.root.appendChild(s);
}

  In this way, our template is completed, one line of rendering work, and so many node operations above are completed. However, this version can be optimized. The similarities in the tpl template can also be extracted. In this way, we can create a template generator and we only need to pass in a different tag name.

//模板生成器 name: 标识
A.view = function(name) {
    
    
	//模板库
	var v = {
    
    
		//代码模板
		code: '<pre><code>{#code#}</code></pre>',
		//图片模板
		img: '<img src="{#src#}" alt="{#alt#}" title="{#title#}" />',
		//带有id和类的模块模板
		part: '<div id="{#id#}" class="{#class#}">{#part#}</div>',
		//组合模板
		theme: [
			'<div>',
				'<h1>{#title#}</h1>',
				'{#content#}',
			'</div>'
		].join('')
	}
	//如果参数是一个数组,则返回多行模板
	if(Object.prototype.toString.call(name) === '[object Array]') {
    
    
		//模板缓存器
		var tpl = '';
		for(var i = 0, len = name.length; i < len; i++) {
    
    
			//模板缓存器追加模板
			tpl += arguments.callee(name[i]);
		}
		//返回最终模板
		return tpl;
	} else {
    
    
		//如果模板库中有该模板则返回该模板,否则返回建议模板
		return v[name] ? v[name] : ('<' + name + '>{#' + name +'#}</' + name + '>');
	}
}

  With this small template generator, we first obtain a much simpler template, for example, we want to get a '<span> span {# #} </ span>' , it can A.view ( 'span') mode To get it. With it, it is much easier to complete our needs.

//文字列表展示
'listPart': function(data) {
    
    
	//......
		//模块模板
		tpl = A.view(['h2', 'p', 'ul']),
		//列表项模板
		liTpl = A.formateString(A.view('li'), {
    
    li: A.view(['strong', 'span'])}),
	//......
}

  The application of template strings is actually very extensive, and you must be familiar with this part of the content.




Guess you like

Origin blog.csdn.net/EcbJS/article/details/111316357