Web components using Polymer. Case study

Юрий Дадычин

FE DM, Levi9

Case study

Как возник кейс

  • Однажды
  • Решил заработать в интернете
  • Блог, блог с рекламой

Бизнес идея

  • Блог
  • Ничего особенного
  • Посты от людей
  • сожрал.com

Тех. решения 

  • Wordpress
  • Бесплатная тема
  • Бесплатные плагины
  • Почти готово

Кастомизация

  • Форма добавления поста
  • Знаете, сверху такая, тип поле
  • Простая но с крутилками и кнопками

Начальная форма

Раскрытая форма

Что взять для кастома?

  • Angular2?
  • На другое просто не стоит тратить время
  • Но Angular2 слишком сам в себе
  • Нужен просто компонент на странице 

Компонент...

Компонент

  • Инкапсулирует логику
  • вставил и забыл
  • минимальный скафолдинг
  • как и ожидается от JS
  • Web-component(далее WC :))

Polymer

Попросту самая завершенная реализация

WC

bower.json

{
  "name": "sj-post",
  "main": "components/sj-new-post.html",
  "dependencies": {
    "webcomponentsjs": "webcomponents/webcomponentsjs#^0.7.0",
    "polymer": "Polymer/polymer#^1.4.0",

    "iron-ajax" : "https://github.com/PolymerElements/iron-ajax.git#1.2.0"
  },
  "devDependencies": {
  }
}

Компоненты в bower_components

.
├── iron-ajax
│   ...
│   ├── hero.svg
│   ├── index.html
│   ├── iron-ajax.html
├── polymer
│   ...
│   ├── polymer-micro.html
│   ├── polymer-mini.html
│   └── polymer.html
├── promise-polyfill
│   ....
│   ├── package.json
│   ├── promise-polyfill-lite.html
│   └── promise-polyfill.html
└── webcomponentsjs
    ...
    ├── webcomponents-lite.js
    ├── webcomponents-lite.min.js
    ├── webcomponents.js
    └── webcomponents.min.js

Содержание компонента

.
├── README.md
├── index.html
└── sj-new-post.html

Структура компонента

<link rel="import" 
  href="../../bower_components/polymer/polymer.html">  <-- Импорт зависимостей
...
<dom-module id="sj-new-post">
  <template>
    <style> <-- Стили компонента
      ...
    </style>
    <iron-ajax <-- Разметка 
      ...
      debounce-duration="300"></iron-ajax>
    <form id="featured_upload" method="post" 
      action="{{action}}" on-submit="submitForm"
      enctype="multipart/form-data">
     ...
    </form>
  </template>
  <script>
    Polymer({ <-- Логика компонента 
      is: 'sj-new-post',
      properties: {
        action: { type: String, value: ''},
        ...
      },
      handleInputClick : function() {...},
      ...
    });
  </script>
</dom-module>

<import/>

<link rel="import" <-- Обязательная зависимость на полимер
    href="../../bower_components/polymer/polymer.html"
    >

<link rel="import" <-- Подключение других компонентов
    href="../../bower_components/iron-ajax/iron-ajax.html"
    >

<style/>

<style>
  :host { <-- Стили родительского компонента
    display: block;
  }

  textarea { <-- Далее как обычно
    width: 100%;
    height: 200px;
  }
  ...
</style>

<template/>

<iron-ajax <-- АПИ компонент
    id="savenewpost"
    url="{{action}}"
    handle-as="json"
    method="POST"
    on-request="handleRequest"
    on-response="handleResponse"
    on-error="handleResponse"
    debounce-duration="300"></iron-ajax>

<form id="featured_upload" method="post" <-- Форма
  action="{{action}}" on-submit="submitForm" 
  enctype="multipart/form-data"
  >
 <input
  type="text"
  placeholder="{{placeholder}}"
  value="{{title}}"
  on-click="handleInputClick"
  name="post_title"
  id="post_title"
  ></input>
  <section hidden$="{{!fullView}}">
    ...
  </section>
</form>

<script/>

<script>
  Polymer({
    is: 'sj-new-post', <-- Имя компонента
    properties: { <-- Они же артибуты 
      action: {type: String, value: ''},
      ...
    },
    handleInputClick : function() {...}, <-- Обработчики событий
    ...
    submitPost : function() {
      var formData = new FormData();
      ...
      this.$.savenewpost.body = formData; <-- Данные поста 
      ...
      this.$.savenewpost.generateRequest(); <-- Делаем запрос
    },
    ...
    handleResponse : function() {
      this.inProgress = false;
      this.fire( <-- Файрим событие 
        'postadded',
        this.$.savenewpost.lastResponse.data);
    },
    ...
  });
</script>

Events

handleResponse : function() {
  this.inProgress = false;
  this.fire(
      'postadded',
       this.$.savenewpost.lastResponse.data
  );
}

Events listeners вне компонента 

$(function(){
	$('#sj-new-post')
        .on(
            'postadded', 
            function(){
		window.location.reload();
	    }
        );
});

Работает везде

  • Angular2
  • REACT
  • $
  • везде прямо как <input/>

Выводы 

  • Вы не сможете построить приложение одними WC
  • Но вы сможете очень быстро построить приложение используя WC 

Ссылки

Спасибо

Web components using Polymer. Case study

By Yuriy Dadichin

Web components using Polymer. Case study

Как я Polymer использовал

  • 755