Модульность, разработка компонентов, шаблонизация

Технопарк, весна, 2018 г.

Модули JavaScript
Слайды доступны по ссылке
frontend-park-mailru.firebaseapp.com

Замыкания!
или как работает JavaScript

Лексическое окружение

Все переменные внутри функции — это свойства специального внутреннего объекта LexicalEnvironment, который создаётся при её запуске

		function sayHello(name) {
		    const magicNumber = 42;
		    console.log(`Hello, ${name}`);
		} 
		 
		sayHello('Лаврентий'); 
		// LexicalEnvironment = {name: 'Лаврентий', magicNumber: 42}
		 
	

Внешние переменные

		var otherName = 'Ivan'; // window.otherName = Ivan
		 
		function sayHello(name) {
		    let magicNumber = 42;
		    console.log(`Hello, ${otherName}`);
		}
		 
		sayHello('Лаврентий'); 
		// LexicalEnvironment = {name: 'Лаврентий', magicNumber: 42}
		// sayHello.[[Scope]] = window
		 
	

Демонстрация

Внешние переменные

		function sum(operand1) {
		    return function(operand2) {
		        console.log(operand1 + operand2);
		    }
		}
		 
		let plus3 = sum(3);
		plus3(6); // 9
		 
	

Внешние переменные

Приватные переменные

		function sum(operand1) {
		    let privateOperand = 1;
		    return function(operand2) {
		        console.log(operand1 + operand2 + privateOperand);
		    }
		}
		 
		let plus3 = sum(3);
		plus3(6); // 10
		 
	

Имеем функцию

		function f() {
		    let privateVariable = 1;
		 
		    // some code
		};
		 
		f();
		console.log(window.privateVariable);  // undefined
		 
	

Самовызывающиеся функции

Сделаем функцию анонимной

		(function () {
		    let privateVariable = 1;
		 
		    // some code
		})();
		 
		console.log(window.privateVariable);  // undefined
		 
	

Модули

Модуль — функционально законченный фрагмент программы, оформленный в виде отдельного файла с исходным кодом… предназначенный для использования в других программах

Модули

		(function () {
		    let importedModule = window.importedModule;
		 
		    class AwesomeClass {
		        //...
		    }
		 
		    window.exportedModule = AwesomeClass;
		})();
		 
	

Модули — будущее

		// main.js
		import AwesomeClass from './package.js'
		let awesome = new AwesomeClass();
	
		// package.js
		class AwesomeClass {
		  //...
		}
		 
		export default AwesomeClass;
		 
	

caniuse.com

Модульный подход к разработке

Компоненты

Компоненты

Компоненты

Практика

Шаблонизация

Создадим простой элемент

		let data = {text: 'Текст элемента!'};
		let block = document.createElement('div');
		block.classList.add('block');
		    
		let blockEl = document.createElement('div');
		blockEl.classList.add('block__el', 'block__el_mod');
		blockEl.textContent = data.text
		    
		block.appendChild(blockEl);
		 
	

Можно поступить проще

		let data = {text: 'Текст элемента!'};
		let block = document.createElement('div');
		block.innerHTML = `
		    <div class="block"> 
		        <div class="block__el block__el_mod">
		           ${data.text}
		        </div>
		    </div>`;
		    
		block.appendChild(blockEl);
		 
	

Микрошаблоны

		<div class="menu">
		    <span class="title"><%-title%></span>
		    <ul>
		        <% items.forEach(function(item) { %>
		            <li><%-item%></li>
		        <% }); %>
		    </ul>
		</div>
		 
	

"Свой" язык

		<fest:template xmlns:fest="http://fest.mail.ru"
		    context_name="json">
		    <div>
		        <h1>Epic Game</h1>
		    </div>
		</fest:template>
		 
	

В результате — JavaScript-код

		;(function(){var x=Function('return this')();if(!x.fest)x.fest={};
		x.fest['fest']=function (__fest_context){"use strict";
		var __fest_self=this,__fest_buf="",__fest_chunks=[],__fest_chunk,__fest_attrs=[]
		,__fest_select,__fest_if,__fest_iterator,__fest_to,__fest_fn,__fest_html="",
		__fest_blocks={},__fest_params,__fest_element,__fest_debug_file="",
		__fest_debug_line="",__fest_debug_block="",__fest_htmlchars=/[&<>"]/g,
		...
		...
		return __fest_html+__fest_buf;} else {return __fest_buf;}}})();
		 
	

Шаблонизация компонент

		<div class="block"> 
		    <div data-bind="text: text" class="block__el block__el_mod">
		        <-- some code -->
		    </div>
		</div>
		<input data-bind="value: name, valueUpdate: 'input'" />
		 
	

Практика

Дополнительные материалы

Всем спасибо!