LINUX.ORG.RU

Есть движок шаблонов для реального DOM

 , , ,


0

1

Здравствуйте

Изучаю 4 столпа веб компонентов: shadow dom, html templates, html imports, custom elements. В процессе возник когнитивный диссонанс. Они, ахах, представляете, предлагают вручную присваивать значения DOM-елементам шаблона:

img.setAttribute("hidden", "");
el.querySelector("span").innerHTML = "YOBA";

Возник очевидный вопрос. Вот есть тысячи шаблонных движков, типа mustache: передаем текст с метками и объект со значениями - получаем текст со вкраплениями этих значений. А есть ли в природе движки, которые вместо текста принимают DOM-елемент, пробегаются по всем аттрибутам и текстовому контенту и заменяют «{{caption}}» на model.caption? Например:

<template id="pic-template">
  <div yoba-hidden>
    <img src="{{icon}}">
    <span>{{Caption}}</span>
  </div>
</template>
let model = { hidden: true; icon: "yoba.png"; caption: "YOBA" };
// el - это не текст, а готовый DOM элемент
let el = document.querySelector("#pic-template").content;
yoba_update(el, model)

PS: судимых и пьющих предлагающих React не беспокоить )

★★★★★

Последнее исправление: makoven (всего исправлений: 2)

предлагающих React

ок, AngularJS тогда

Dred ★★★★★
()

есть, MVVM называются (modelview паттерн), когда-то это был Knockout (начни с него), теперь это везде есть, плагинами или искаропки. Эх, помню как еще Knockback задрачивал, летит время.

anonymous
()
Ответ на: комментарий от anonymous

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

anonymous
()

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

anonymous
()
Ответ на: комментарий от anonymous

сам подумай, во сколько встант рекурсивный обход дом интерфейса

Сам рекурсивный обход думаю вообще не ощутится

А ресурсозатраты по обновлению значений в dom-элементах будут точно такие же, что и ручным способом

makoven ★★★★★
() автор топика
Ответ на: комментарий от anonymous

есть, MVVM называются

Все MVVM либы что я видел, выходят далеко за рамки моих нескромных запросов. Там и кастомные теги, и встроенные <if>, <each>, и двустороннее связывание. Мне бы чего-нибудь навроде mustache, но для DOM

makoven ★★★★★
() автор топика
Ответ на: комментарий от makoven

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

let value = node.style.backgroundColor

value = «red» ? — вот такой «шаблонизатор» или что блин?

anonymous
()
Ответ на: комментарий от makoven

Сам рекурсивный обход думаю вообще не ощутится

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

Движков которые колбасят по реальному DOM не знаю. Все что видел - виртуальный используют.

Vit ★★★★★
()
Ответ на: комментарий от Vit

Обычно стараются в DOM только писать, и никогда не читать

А в чем проблема с чтением DOM-а? Это ж просто получение значения метода нативного объекта, без какого-либо влияния на рендеринг

makoven ★★★★★
() автор топика
Последнее исправление: makoven (всего исправлений: 1)
Ответ на: комментарий от makoven

Ну там анимация может происходить, скрол, и стили перекрываться родителями + зависить от мышки и т.п. Еще reflow бывает при апдейте совершенно посторонних элементов.

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

Поэтому делают VDOM, а оттуда уже копируют diff-ы через requestAnimationFrame.

То что ты написал технически возможно, но не особо нужно.

Vit ★★★★★
()
Ответ на: комментарий от Vit

Из твоих слов получается, что будет медленно, если читать стили. Чтение src у <img> или textContent врят-ли замедлится анимацией или скроллом. И еще вопрос, что дешевле прочитать - значения встроенных C++ объектов или созданных мною js-объектов

Да и вообще, вопрос производительности мне до лампочки. Если будет работать на моем китаефоне - значит все ок. Жаль что никто ничего такого не встречал. Я тоже не нашел

То что ты написал технически возможно, но не особо нужно

Для веб-компонентов в их каноничном исполнении, с <template> и shadow dom очень даже втему

makoven ★★★★★
() автор топика
Последнее исправление: makoven (всего исправлений: 3)
Ответ на: комментарий от makoven

Не знаю как DOM-объекты устроены внутри. Поэтому не могу утверждать однозначно, где блокировки будут, а где нет.

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

Vit ★★★★★
()
Ответ на: комментарий от makoven

Это одна и та же библиотека просто под разными именами. Да она компилит, но не htm а сразу dom, а потом работает с dom напрямую. Я и говорю что возможно в кишка есть куски которые делают то что тебе надо или могут служить отправной точкой.

novoxudonoser
()
Ответ на: комментарий от int64

слоты больше для написания html-а пользователями вручную. Полученный по сети json вставлять в слоты как-то нелогично. Да не все сценарии из примера в subj слотами решаются

makoven ★★★★★
() автор топика
Ответ на: комментарий от makoven

json и DOM\html связаны между собой чуть менее, чем никак. Можешь генерировать из полученного json'а dom фрагмент со слотами, под который у тебя уже есть темплейт.

В ОП-посте ты спрашивал про динамическую подстановку, как в шаблонизаторах же. Вот, в нативном шаблонизаторе DOM для этого используют узлы slot и аттрибут slot, чтобы динамически что-то куда-то подставлять. Если ты хочешь чего-то большего (другие форматы, отлчные от DOM узлов), то это уже не нативщина и пилится поверх, что логично.

int64
()
Ответ на: комментарий от int64

Можешь генерировать из полученного json'а dom фрагмент со слотами, под который у тебя уже есть темплейт

Да-да. А генерить этот фрагмент можно используя mustache. Можно обжечься градусом предлагаемого тобой безумия)

Вот, в нативном шаблонизаторе DOM для этого используют узлы slot и аттрибут slot, чтобы динамически что-то куда-то подставлять

Слоты - для декларативного описания компонента ручками. В процессе работы приложения (когда прилетело событие), элемент придется менять програмно не важно в слоте этот элемент или нет

Если ты хочешь чего-то большего (другие форматы, отлчные от DOM узлов)

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

<img src="{kartinko}">

makoven ★★★★★
() автор топика
Последнее исправление: makoven (всего исправлений: 3)
Ответ на: комментарий от makoven

Я хочу обычный html, у которого в строковых значениях прописаны маркеры <img src=«{kartinko}»>

https://developer.mozilla.org/en-US/docs/Web/API/Document/createTreeWalker

Да-да. А генерить этот фрагмент можно используя mustache. Можно обжечься градусом предлагаемого тобой безумия)

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

int64
()
Ответ на: комментарий от makoven

Это вроде как надо для корректно работающей схемы с серверной шаблонизацией - клиент приходит первый раз, nodeJS на сервере сгенерил html отдал клиенту, клиент его отрендерил, включил js вместе с monkberry , тот распарсил html и создал из него модели. (чтобы 2й раз за теме же данными только в json не ходить на сервер)

novoxudonoser
()
Ответ на: комментарий от makoven

не пойму чего оп хочет, создать объект и вместо реального значения сделать там {{ var }} а потом заменить {{ var }} на «14px» вызовом типа объект.ЗаменитьПлейсхолдерНоЯНеЗнаюВКакомСвойстеОнЛежит или что блин? может я тупой, объясните еще раз, лень перечитывать оппост, так как с первого раза ничего не понял

anonymous
()
Ответ на: комментарий от makoven

как я и предполагал, у тс ошибка в дизайне днк и он хочет ненужного. подумай сам почему такого до сих пор нет, разве ты не знаешь по значению в каком свой стве оно доступно? идиотизм из О(1) делать о(Н) алгоритм, идиотизм спрашивать о таком, а вроде умный человек, а такие глупости лепит, жуть.

anonymous
()
Ответ на: комментарий от anonymous

разве ты не знаешь по значению в каком свой стве оно доступно?

Аргументация уровня: зачем мне render(«Hello, {who}», {who: «world»}) когда можно написать просто «Hello, world»

makoven ★★★★★
() автор топика
Ответ на: комментарий от makoven

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

anonymous
()
Ответ на: комментарий от makoven

я наверное недоходчиво для такого как ты ламера выразился: приведи практический пример использования своей технологии, когда например ты не знаешь в какое именно свойство хочешь подставить то или иное значение, что надо перебрать весь объект (рекурсивно) и как отличать плейсхолдеры от реальных значений (чуешь разницу между биндингами или сеттерами), как производить «перерендеринг» и все тому подобное, вроде не глупый человек, раньше твою аватару замечал, а тут такое городит, как будто и строки кода в жизни не написал. такие они, линуксоиды.

anonymous
()
Ответ на: комментарий от makoven

эмуляцию дом затем и сделали, что перерендерить весь документ (читай фрагмент) оказалось быстрее чем заменять значения в объекте (перерисовка после каждой замены, чуешь смысл, некромант?)

anonymous
()
Ответ на: комментарий от anonymous

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

const _ = require("../../bower_components/lodash/dist/lodash.js")

const template = {
	some: {
		property: "{{ To Replace }}"
	},
	another: {
		search: {
			leaf: "{{ duqu }}"
		}
	}
}

class Template {
	constructor(layout) {
		this.layout = layout
		_.bindAll(this, ["visit", "replace"])
	}

	visit(tree, data) {
		_.each(tree, leaf => {
			_.isObjectLike(leaf) && this.visit(leaf, data) || this.replace(leaf, data)
		})
		return tree
	}

	replace(leaf, data) {
		console.log(leaf, data)
	}

	render(data) {
		return this.visit(this.layout, data)
	}
}

console.log(JSON.stringify(new Template(template).render({"To Replace": "Its Data", "duqu": "QOODOO"})))

anonymous
()
Ответ на: комментарий от anonymous

эмуляцию дом затем и сделали, что перерендерить весь документ (читай фрагмент) оказалось быстрее чем заменять значения в объекте

Проверял или реактивные мальчики на хабрахабре нашептали?

makoven ★★★★★
() автор топика
Последнее исправление: makoven (всего исправлений: 1)
Ответ на: комментарий от anonymous

приведи практический пример использования своей технологии

Не то чтоб это моя технология. В Polymer нечто подобное реализовано. Но он слишком жирный и слишком отдалился от W3C-вебкомпонентов чтобы захотелось им пользоваться

makoven ★★★★★
() автор топика
Ответ на: комментарий от makoven

еще не знает зачем но уже знает что и почему другое не подходит, вся суть

anonymous
()

Ну уже ответили, angular, он использует виртуальный DOM только с целью оптимизации, без этого более-менее сложные страницы твой браузер будет просто тормозить, а не переваривать.

ixrws ★★★
()

AiKi Engine

Вот пара примеров из AiKi Engine (http://www.digiport.ru)

<?php
include($_SERVER["DOCUMENT_ROOT"]."/engine/engine.php");
$out=aikiFromString("<nav><ul class='mainmenu'>
     <li><a href='#home'>Home</li>
     <li><a href='#about'>About</li>
     <li><a href='#service'>Service</li>
     <li><a href='#price'>Price</li>
</ul></nav>");

// Добавляем пункт меню после всех
    $out->find(".mainmenu")->append("<li><a href='/sample.htm'>Sample</li>");

// выводим результат
   echo $out->outerHtml();
?>
=====================
<?php
include($_SERVER["DOCUMENT_ROOT"]."/engine/engine.php");
$out=aikiFromString("
    <div>
        <h3>Уважаемый, {{name}}</h3>
        <p>Всвязи с накопившейся задолженностью, просим вас просим вас погасить её в кратчайшие сроки.</p>
        <ul>
            <li>{{period[0][month]}} - {{period[0][summ]}} руб.</li>
            <li>{{period[1][month]}} - {{period[1][summ]}} руб.</li>
        </ul>
        <p>Итого, на сумму {{total}} рублей.</p>
        <p>С уважением, Администрация.</p>
    </div>
");
$Item=array(
    "name"=>"Сергеев Андрей Васильевич",
    "total"=>800,
    "period"=>array(
                0=>array("month"=>"сентябрь","summ"=>500),
                1=>array("month"=>"октябрь","summ"=>300),
                )
);
$out->contentSetValues($Item);
echo $out->outerHtml();
?>
Это не то что требуется?

digiport
()
17 октября 2018 г.
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.