Съел HTML на рендеринге собаки

Съел HTML

на рендеринге

собаки


автор названия
© @saitonakamura

Александр Коротаев

  • VK.com Санкт-Петербург
  • 10 лет в веб-разработке
  • помогаю в SPB-Frontend
  • ПК в JSNation

web-standards-ru/cfp-list

React?

Angular?

Vue?

А если их не станет?

Поиск по NPM

Проблема 1


Низкие

уровни

абстракции

В чистом виде

            const {screen, box} = require('blessed')
            const myScreen = screen({...})
            const myBox = box({...})
             
            myScreen.append(box)
            myBox.render()
        

Идем далее

            const showBox = () => {
              myScreen.append(box)
              myBox.render()
            }

            const hideBox = () => {
              myScreen.unmount(box)
              myScreen.render()
            }
        

Проблема

  1. Очистка
  2. Триггеры
  3. Перерисовки

Проблема 2



Боль

наследования

Создаем список

            const addChild = (parent, item) => {
              parent.append(item)
              parent.render()
            }
             
            addChild(myScreen, box({...}))
            addChild(myScreen, box({...}))
        

Фильтруем список

            const filter = (parent, filterFn) => {
              return parent.children.filter(filterFn)
            }
            const filtered = filter(myScreen, i => i.checked)
             тут все заново пересоздаем 
            myScreen.render()
             
        

Так не пойдет

FIXME: обновление layout
REFACTOR: наследование
TODO: позиционирование

Как я до этого дошел?

  1. Telegram в консоли
  2. Игры на React

Согласователь (Reconciler)

Код рендера

            ReactFiberReconciler({
              appendChild: () => ...
              commitMount: () => ...
              commitUpdate: () => ...
              createInstance: () => ...
              removeChild: () => ...
              ...
            })
        

Инстансы по имени тега

            const createInstance = (type, props) => {
              switch (type) {
                  case 'Container': return new PIXI.Container(props)
                  case 'Sprite': return new PIXI.Sprite(props)
                  default: return throw Error()
              }
            }
        

Все параметры объектом

            const commitUpdate = (
              instance, payload, type, lastProps, nextProps
            ) => {
              const diffProps = getDiff(lastProps, nextProps)
              
              Object.assign(instance, diffProps)
            }
        

Остановите Reconciler!

Renderer2

Фабрика (RendererFactory2)

            class MyRendererFactory implements RendererFactory2 {
              createRenderer(hostElement: any
                             type: RendererType2 | null
              ): Renderer2 {
                return new MyRenderer(hostElement)
              }
            }
        

Renderer2

            class <T>MyRenderer implements Renderer2 {
              createElement(name: string): T
              addClass(el: T, name: string)
              setAttribute(el: T, name: string, value: string)
              setProperty(el: T, name: string, value: any)
              removeChild(parent: T, oldChild: T)
            }
        

Реализация рендера

            const data: { [p: string]: any } = {}
            createElement = (name: string): T => {
              return data[generateId()] = new Element()
            }
            setAttribute = (el: T, name: string, value: string) => {
              applyProps(el, name, value)
            }
        

applyProps

            const render$ = new Subject()
            applyProps = (el: T, name: string, value: string) => {
              el[name] = value
              render$.next(el)
            }
            render$.pipe(debounceTime(100)).subscribe(realRender)
        

Приколочено гвоздями!

window.Vue.use()

VueRenderer

            const componentFiles = {...files...}
            const VueRenderer = {
              install (Vue, options) {
                  componentFiles.keys().forEach(key => {
                      Vue.component(key, componentFiles[key])
                  }
              }
            }
        

use VueRenderer

            if (window !== undefined && window.Vue) {
              window.Vue.use(VueRenderer)
            }
        

Реактивная модель


Внезапно, DOM

когда хочется
вечных ценностей...

Браузер как парсер

            <canvas>
              <box left="10" top="10" right="10" bottom="10" >
                  <text size="20">Привет, HolyJS!<text>
              <box>
              <button>Далее</button>
            </canvas>
        

MutationObserver

            const config = {
              attributes: true, childList: true,
              characterData: true, subtree: true,
            }
            const observer = new MutationObserver(callback)
            observer.observe(element, config)
              
        

MutationObserver callback

            function(mutations) {
              mutations.forEach(mutation => {
                  if (mutation.type === 'childList')
                      ...
                  if (mutation.type === 'attributes')
                      ...
                      
        

Костыляция!

Суть




Как все это

готовить?

Графика!

+

Консоль!

+

Email!

+

PDF!

+

Выводы




мы многое

поняли...

Это было в 1986

Интерфейсов уже нужно было настолько много, что появились отдельные разработчики для них

Ссылка на статью с полным рекламным роликом Action!
Lisp
1986
-->
SGML
1986
-->
QML
2009
-->
Flutter
2015
-->
SwiftUI
2019
            (make-instance 'button'
              :text "Hello"
              :command (lambda ()
                  (format t "clicked")))
        
Lisp
1986
-->
SGML
1986
-->
QML
2009
-->
Flutter
2015
-->
SwiftUI
2019
Sounds
Good
Maybe
Later
Lisp
1986
-->
SGML
1986
-->
QML
2009
-->
Flutter
2015
-->
SwiftUI
2019
            Rectangle {
              width: 200
              color: "blue"
              Image {
                  source: "pics/logo.png"
              }

        
Lisp
1986
-->
SGML
1986
-->
QML
2009
-->
Flutter
2015
-->
SwiftUI
2019
            MaterialApp(
              title: 'Welcome to Flutter',
              home: Scaffold(
                  appBar: AppBar(title: Text('Welcome to Flutter'))
                  body: Center(child: Text('Hello World'))
              )

        
Lisp
1986
-->
SGML
1986
-->
QML
2009
-->
Flutter
2015
-->
SwiftUI
2019
            some View {
              List(model.items) { item in
                  Image(item.image)
                  VStack(alignment: .leading) {
                      Text(item.title)
                  }

        

Интерфейсы

Повышайте уровни абстракции

Соединяйте

Ссылки

@mamu_eval
github.com/lekzd
Telegram: @lekzd