Объектно-ориентированная альтернатива jquery

от автора

Много кто использует jquery в своих проектах, в связи с простотой и легкостью, с которой его можно подключить на страницу, несмотря на то что существует достаточное количество объектно ориентированных фреймворков с компонентным подходом. Однако почти все они создают html разметку из javascript кода, что не всегда удобно, для совместного их использования с другими библиотеками, также создание разметки на js занимает какое-то время на стороне клиента, либо приходится делать серверный рендеринг на node.js что исключает их использование с другими языками например php.

Получается нужно постоянно выбирать, сравнивать все плюсы и минусы, или учить несколько фреймворков для разных проектов, для одного jquery, второго angular, а для будущего присматриваться к vue.js.

Было-бы здорово иметь один инструмент который может справиться со всеми требуемыми задачами, а именно:

  1. Встраиваться в уже отданную сервером страницу, без необходимости серверного рендеринга на node.js и возможность использования его с любыми другими библиотеками
  2. Иметь объектно-ориентированный, компонентный подход построения приложения, четкую и понятную структуру, возможность наследования свойств.
  3. Легкость в изучении, небольшой размер, производительность, возможность применять его как в маленьких так и больших проектах, а также для создания виджетов, слайдеров и т.д.

Как вы наверное уже догадались, здесь я как раз и хочу его представить — htmlix.js

Фреймворк встраивается в уже отданную сервером страницу с помощью data- свойств.
Таким образом нам не нужно создавать шаблоны на каком либо другом языке в js коде, мы просто используем уже готовый html.

Далее создадим небольшое приложение, чтобы в сжатом виде познакомиться со всеми основными особенностями фреймворка.

Уже готовый, похожий пример можно покликать здесь.

После ввода имени пользователя в форму, приложение отобразит его имя в приветствии, кнопке выхода, отобразит сообщение о новом посетителе и создаст новый контейнер в массиве с пользователями, а также сохранит данные в localStorage. После перезагрузки страницы, возьмет имя из localStorage. При клике по кнопке «выйти из профиля» удалит данные со всех компонентов и переменную из localStorage и отобразит сообщение о выходе посетителя.

Давайте создадим четыре компонента: форму входа — form, приветствие — greeting, кнопку выхода — logout и массив со всеми посетителями — users_array.

Создадим html разметку всех компонентов:

<!--  компонент - контейнер форма с двумя свойствами input c типом свойства "inputvalue" и  click с типом "click" -->  <form data-form="container" class="card col-12">    <div class="form-group">        <label for="">Введите имя</label>       <textarea data-form-input="inputvalue" class="form-control" rows="1"></textarea>     </div>     <button data-form-click="click" type="submit">Submit</button> </form>  <!-- компонент - контейнер приветствие и свойство user_name с типом - "text" -->  <div data-greeting="container" class="col-6 card">                 <p>Привет: <span  data-greeting-user_name="text">guest</span></p> </div>   <!-- компонент - контейнер кнопка выхода и свойство user_name с типом - "text" -->  <div data-logout="container" class="col-6 card">               <a href="#"> Выйти из профиля: ( <span  data-logout-user_name="text"></span>  )       </a>                 </div>   <!-- компонент - массив пользователей, изначально с двумя контейнерами, в каждом контейнере свойство user_name - "text", и свойством массива  message с типом "text" для отображения сообщений -->   <div data-users_array="array">      <p  data-users_array-message="text" > </p>		 	 <div  class="row"> 		             <div data-user="container" class="col-4 card"> 		<p>пользователь - <span data-user-user_name="text">user_name_1</span>                  </p> 	     </div> 			              <div data-user="container" class="col-4 card"> 		 <p>пользователь - <span data-user-user_name="text">user_name_2</span>                   </p> 	      </div> 		         </div>	 </div>	 		 

В коде выше мы создали четыре компонента: три из них с типом «container» и один с типом «array» — массив со всеми посетителями. Контейнер — это компонент, в котором сгрупированы, какие либо html свойства, например текст, атрибут, слушатель события и т.д. Все свойства имеют определенный тип. Массив это компонент для работы с однотипными контейнерами, у массива так-же как и у контейнера могут быть различные свойства.

В примере выше мы указали свойства в html разметке с помощью data- атрибутов, также свойства можно указать с помощью селекторов из javascript кода, чтобы не писать их в разметке.

Теперь перенесем их в javascript:

var StateMap = {      form: {//форма входа         container: "form",         props: ["input", "click"],         methods: {              click: function(){                 event.preventDefault(); //отменяем перезагрузку страницы                                   //this - указывает на свойство, в обработчике события которого мы находимся, parent - доступ к контейнеру из свойства                 //получаем данные свойства input                  var text = this.parent.props.input.getProp();                  console.log(text);                                       }                    },           },       greeting: {//приветствие          container: "greeting",         props: [ "user_name", ],          methods: {             }     },     logout: { //кнопка выхода          container: "logout",         props: [ "user_name", ],          methods: {         },       },     users_array: { //массив с пользователями          selector: "div.row", //уточняющий селектор 	arrayProps: [ "message"], //свойство массива           container: "user",  //контейнер массива         props: [ "user_name", ], //свойство контейнера         methods: {                 },               }, } window.onload = function(){//создаем экземпляр приложения htmlix      var HM = new HTMLixState(StateMap);     console.log(HM);     } 

В примере выше мы перенесли компоненты в javascript код. В компоненте form свойстве click мы записываем данные введенные пользователем в переменную text и выводим их пока-что в консоль. Далее эти данные мы будем использовать во всех оставшихся компонентах. Для того чтобы компоненты узнали о том что данные обновились мы будем использовать пользовательские события.

Добавим событие «emiter-set-name»:

eventEmiters: {  //добавляем объект со всеми пользовательскими событиями в описание приложения 		    ["emiter-set-name"]: {prop: ""}, //событие с начальными данными 		 },   ///вызываем событие в свойстве click компонента form и передаем в него полученные данные click: function(){         event.preventDefault();          var text = this.parent.props.input.getProp();          this.rootLink.eventProps["emiter-set-name"].setEventProp(text);            //сохраняем имя пользователя в localStorage                           window.localStorage.setItem('user_name', name);  }    //слушаем событие во всех остальных компонентах и обновляем их свойства greeting: {      container: "greeting",      props: [ "user_name", ['listen_set_name', "emiter-set-name", "" ],], //создали свойство слушатель события в компоненте       methods: { 			           listen_set_name: function(){ 		//получили данные из события и обновили свойство user_name 		this.parent.props.user_name.setProp( this.emiter.getEventProp() ); 	  }			        },		 },   logout: {  		    container: "logout",    props: [ "user_name",  ['listen_set_name', "emiter-set-name", "" ] ],     methods: { 			 	 listen_set_name: function(){//слушаем событие и обновляем свойство user_name 				 	    this.parent.props.user_name.setProp( this.emiter.getEventProp() ); 	},			     },	 },    users_array: {   	selector: "div.row", 	arrayProps: [    "message",  ['listen_set_name', "emiter-set-name", ""],	],  	arrayMethods: { 							 	   listen_set_name: function(){//слушаем событие в свойстве массива и создаем новый контейнер с полученными данными 				 	            this.parent.add( {user_name: this.emiter.getEventProp()} );                                         //выводим сообщение о новом посетителе                     this.parent.props.message.setProp("новый посетитель - "+this.emiter.getEventProp());  								 	    },		 	container: "user", 	props: [ "user_name", ], 	methods: { 	},        	 },    window.onload = function(){  	var HM = new HTMLixState(StateMap);                  //проверяем есть ли переменная  user_name в  localStorage и при ее наличии вызываем событие  	var name = window.localStorage.getItem('user_name');	 	if(name != null)HM.eventProps["emiter-set-name"].setEventProp(name);   	console.log(HM); 	 }	  

В коде выше мы создали пользовательское событие которое одновременно служит хранилищем для меняющихся данных, затем в каждом компоненте добавили свойство-слушатель данного события, чтобы при обновлении данных произвести изменения в каждом компоненте.

Теперь создадим событие «emiter-exit-user» для выхода пользователя:

	eventEmiters: { 		/*      ...        */ 		["emiter-exit-user"]: {prop: ""},  		 	}             //вызываем событие в компоненте logout и передаем в него имя пользователя logout: { 		     container: "logout",     props: [ /* ...  */,  ["exit", "click", "a:first-of-type"],], //создали новое свойство - слушатель события "click" и указали его вторым способом с помощью массива        methods: {            /* ... */ 	   exit: function(){ 	      //получаем имя пользователя 	     var user_name = this.parent.props.user_name;  	     //вызываем событие		 	     this.rootLink.eventProps["emiter-exit-user"].setEventProp( user_name.getProp() );  	                     //удаляем пользователя из localStorage 	     window.localStorage.removeItem('user_name');                                //очищаем свойство компонента 	      user_name.setProp(""); 	    }			 	},	 },   users_array: {   	selector: "div.row", 	arrayProps: [ /* .. */,   ['listen_exit_user', "emiter-exit-user", ""], ], //добавили свойство - слушатель события  "emiter-exit-user"  	arrayMethods: { 		/* ... */ 		listen_exit_user: function(){ 			//data - доступ ко всем контейнерам из массива 			this.parent.data.forEach(container=>{ 					 				if(container.props.user_name.getProp() == this.emiter.getEventProp()){ 						 				         container.remove(true); //удалили контейнер  				}					 			});                   //добавили сообщение			                  this.parent.props.message.setProp( this.emiter.getEventProp()+" - покинул сайт"); 			},			 		},		 		container: "user", 		props: [ "user_name", ], 		methods: { 		},        	 },	   greeting: { 		 		container: "greeting", 		props: [/* ... */, ['listen_exit_user', "emiter-exit-user", ""] ],  		methods: { 			 			listen_exit_user: function(){  			       //удалили имя пользователя из свойства 				this.parent.props.user_name.setProp(""); 			}			 		},		 	},  

Это был краткий обзор основных принципов построения приложения на htmlix, полный код данного примера, вместе с использованием вспомогательных методов можно посмотреть здесь.

ссылка на оригинал статьи https://habr.com/ru/post/509502/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *