новый фреймворк GoogleLit
, Фреймворк с благословения Google вызвал у меня интерес, поэтому я пошел вкратце разбираться, и просто поделился с вами результатами обучения. из-заLit
Фреймворк все еще находится в экспресс-итерации. Некоторые реализации кода, упомянутые в статье, скорее всего, подверглись рефакторингу. Заинтересованные студенты могут ознакомиться с ним.Lit
исходный код.
Что такое ЛИТ
Lit
основывается наWeb-Component
Созданный интерфейсный фреймворк, предшественник можно в основном понимать какPolymer
,Lit
Обеспечивает следующие конкурентные функции
-
на основе
Web-Component
Инкапсуляция более высокого уровня обеспечивает адаптивные данные и декларативные шаблоны, которые используются в современной интерфейсной разработке, сокращая часть стандартного кода веб-компонентов. -
маленький. Только 5K во время выполнения
-
Мощная производительность. избегали
VDOM
Некоторые недостатки: обработка только асинхронной части пользовательского интерфейса при обновлении (это можно понимать как обработку только адаптивной части). -
Совместимость лучше. потому что
web-component
Это родная способность HTML, что означаетweb-component
Может использоваться везде, где используется HTML, независимо от фреймворка.
Тот факт, что он не имеет ничего общего с фреймворком, является ключевым моментом, который побудил меня обратить внимание на этот фреймворк (svelte тоже есть, у меня есть время говорить о нем, я не могу его изучить), потому что для каких-то общих дел коды,бежать как можно меньшеа такженезависимый от фреймворкаЭто два основных технических показателя отбора.
Что такое веб-компонент
Веб-компоненты — это набор различных технологий, позволяющих создавать многократно используемые настраиваемые элементы — с их функциональностью, изолированной от остального кода — и использовать их в своих веб-приложениях.
Я лично считаю, что компонентизация является важной причиной быстрого развития и расширения интерфейса.Вспоминая время, когда был написан JQ, HTML-код в основном выглядел так:
<div>
<div class="button1" >按钮</div>
<div class="button2 active" >按钮</div>
<div class="button3" >按钮</div>
</div>
Даже если синтаксис шаблона появится позже, ситуация не исправится (взаимодействуя с сервером для совместного использования шаблона -> JSP или для инкапсуляции метода в JS, инжект через синтаксис шаблона -> рули), простой рендеринг цикла может оказаться удобным Решить проблему повторного использования DOM, но повторное использование компонентов на разных уровнях все еще остается проблемой.
Таким образом, компонентизация является важным шагом для любой технологии фреймворка переднего плана, которая хочет развиваться дальше.Web-Component
это возможность создавать повторно используемые элементы (пользовательские компоненты), изначально поддерживаемые браузером, иLit
основывается наWeb-Component
построен.
Тогда нам нужно сначала понять веб-компонент
Простой процесс разработки для веб-компонента
Create a class in which you specify your web component functionality, using the ECMAScript 2015 class syntax
Register your new custom element using the CustomElementRegistry.define() method, passing it the element name to be defined, the class or function in which its functionality is specified, and optionally, what element it inherits from.
If required, attach a shadow DOM to the custom element using Element.attachShadow() method. Add child elements, event listeners, etc., to the shadow DOM using regular DOM methods.
If required, define an HTML template using<template>
and<slot>
. Again use regular DOM methods to clone the template and attach it to your shadow DOM.
Use your custom element wherever you like on your page, just like you would any regular HTML element.
Давайте сначала разберемся в двух основных моментах веб-компонента.Поняв эти два свойства, вы можете создавать свои собственные компоненты.
Пользовательский элемент Пользовательский элемент
Во-первых, нам необходимо обеспечить**CustomElementRegistry**
****Экземпляр интерфейса регистрирует пользовательский элемент, и экземпляр монтируется вwindow.customElements
начальство
ПользовательскийЭлементРеестрdefine
метод может использоваться для регистрации пользовательского элемента, есть два типа на выбор
-
пользовательский элемент: независимый элемент, поведение полностью определяется разработчиком.
-
Настройка встроенных элементов: эти элементы наследуют и расширяют встроенные элементы HTML.
API выглядит следующим образом
customElements.define(name, constructor, options);
nameимя вашего пользовательского элемента (в соответствии сDOMStringстандартный, должен иметь прочерк), взяв приведенный выше пример, вы можете передать<my-component></my-component>
использовать в видеconstructorкомпонент, который мы определяемoptionsОбъявите, какой тип пользовательского элемента мы определяем, в настоящее время доступно только один продлен, указав какой элемент наследовать от.
Когда вы определяете, какой элемент наследовать, метод использования не соответствует пользовательскому элементу, вам нужно использоватьisАтрибуты Предположим, вы определяете собственный встроенный элемент с именем my-paragraph, который наследуется от тега p, тогда при его использовании вам необходимо<p is="my-paragraph"></p>
напиши вот так
В этом случае,Web-Component
Ядро логики лежит в конструкторе.Как мы определяем наш собственный компонент?
В отличие от React и Vue, вы можете написать JSX или синтаксис шаблона в методе рендеринга, чтобы создать дерево VDOM для определения структуры компонента.Web-Component
Он не позволяет писать шаблоны (но это означает, что он может использовать любой синтаксис шаблона). Обычно вы используете обычные манипуляции с DOM для создания структуры компонентов в конструкторе. Возьмите каштан:
class MyComponent extends HTMLElement {
constructor() {
super()
const wrapper = document.createElement('span');
wrapper.setAttribute('class','wrapper');
const info = document.createElement('span');
info.setAttribute('class','info');
info.textContent = this.getAttribute('text') || 'default';
this.appendChild(wrapper);
wrapper.appendChild(info);
}
}
Приведенный выше код создает текстовый узел, вложенный в соответствии с двойным диапазоном.
<my-component></my-component>
<!-- 等价于 -->
<span class="wrapper"><span class="info">default</span></span>
<my-component text="test"></my-component>
<!-- 等价于 -->
<span class="wrapper"><span class="info">test</span></span>
Конечно, просто создавать UI смысла нет, давайте подумаем, какие еще возможности предоставляют современные фреймворки?
Отзывчивый! Привязка к событию! жизненный цикл!
Хорошо, организуй.
Давайте сначала поговорим о более простой привязке событий.Поскольку DOM создается внутри, привязывать события легко (обратите внимание на этот момент).
class extends HTMLElement {
constructor() {
super()
this.handleClick = this.handleClick.bind(this)
const wrapper = document.createElement('span');
wrapper.setAttribute('class','wrapper');
const info = document.createElement('span');
info.setAttribute('class','info');
info.textContent = this.getAttribute('text') || 'default';
this.appendChild(wrapper);
wrapper.appendChild(info);
const button = this.querySelector('#button');
button.addEventListener('click', this.handleClick)
}
handleClick () {
this.parentNode.removeChild(this)
}
}
<my-life-cycle-component>
<button id='button'>Remove this</button>
</my-life-cycle-component>
Приведенный выше код создан на основе предыдущего текста, и есть дополнительная кнопка, нажатие на которую удалит весь пользовательский элемент (конечно, эта кнопка может быть создана и самим компонентом)
Тогда давай поговоримlifecycle, Customeelements.define Принятый конструктор позволяет разработчикам определить следующие несколько жизненных циклов, его будет называться в соответствующее время
-
connectedCallback
: вызывается, когда пользовательский элемент впервые вставляется в DOM документа. -
disconnectedCallback
: вызывается, когда пользовательский элемент удаляется из DOM документа. -
adoptedCallback
: вызывается, когда пользовательский элемент перемещается в новый документ. -
attributeChangedCallback
: вызывается, когда пользовательский элемент добавляет, удаляет или изменяет свои собственные атрибуты.
Проще говоря, это
-
componentDidMount
-
componentWillUnmount
-
Не существует (я не проверял какие-либо сценарии, которые появятся)
-
componentDidUpdate
Поскольку понятия состояния нет, нам нужно вручную обрабатывать все изменения внутренних свойств компонентов, и умственная нагрузка может быть немного выше.Конечно, вы также можете использовать их как атрибуты пользовательских элементов через ~~attributeChangedCallback~~
иметь дело с
Попутно будет выходить callback-ответ с изменениями атрибутов (разумеется, это только основа отзывчивости, изменения атрибутов напрямую не повлияют на внутреннюю логику рендеринга, умственную нагрузку+1)
Если вам нужно инициировать функцию обратного вызова после изменения атрибута элемента, вы должны определитьobservedAttributes()
получить функцию для прослушивания этого свойства
<my-life-cycle-component>
<button id='button1'>Remove this</button>
<button id='button2'>Toggle this</button>
<input />
</my-life-cycle-component>
Глядя на код, здесь определяется компонент с полем ввода.После ввода поля ввода текст внутри компонента будет перерисован. Заодно прослушайте атрибут стиля, а после изменения распечатайте (бессмысленная демонстрация +1)
Тень DOM Тень DOM
Shadow DOM
Преимущества многочисленны.Shadow DOM
Основная функция заключается в следующем: «Он может прикрепить к элементу отдельный DOM (тег стиля тоже принадлежит) (эта DOM скрыта) и не повлияет на внешний стиль, что дает очень мощные веб-компоненты. Возможность инкапсуляции, может полностью скрыть структуру, стиль и поведение компонента снаружи, и изолировать его снаружи»]
Есть понятие, которое требует внимания -Shadow boundary
Shadow boundary
ОтноситсяShadow DOM
где он заканчивается и где начинается обычный DOM. весьshadow dom
Стили и элементы внутри не повлияют на внешний мир больше, чемshadow boundary
спектр.
Shadow Dom не новая вещь - в течение длительного времени в прошлом браузеры использовали его для инкапсуляции внутренней структуры некоторых элементов. С помощью кнопки управления воспроизведением по умолчанию
<video>
элемент например. Все, что вы можете видеть, это<video>
Фактически тег в своей Shadow DOM содержит ряд кнопок и других контроллеров. Стандарт Shadow DOM позволяет вам поддерживать набор Shadow DOM для ваших пользовательских элементов.Цитата из МДН
Итак, как его использовать? Есть основной API,Element.attachShadow({mode: }), теневой корень может быть присоединен к любому элементу, а значение режима открыто или закрыто. Разница в том, можно ли получить структуру shadowDOM извне. Для более глубокого понимания разницы между открытием и закрытием см.blog.Rev ill Web.com/open-vs-eat…Эта статья не будет описывать это здесь.
Итак, возьмем простейший пример выше и сделаем преобразование
customElements.define('my-component', class extends HTMLElement {
constructor() {
super()
const shadow = this.attachShadow({mode: 'open'});
const info = document.createElement('span');
info.setAttribute('class','info');
info.textContent = this.getAttribute('text') || 'default';
// this.appendChild(info)
shadow.appendChild(info);
}
})
Это создает пользовательский элемент на основе shadowDOM. Он ничем не отличается. Давайте попробуем добавить некоторые пользовательские стили.
customElements.define('my-component', class extends HTMLElement {
constructor() {
super()
const shadow = this.attachShadow({mode: 'open'});
const info = document.createElement('span');
info.setAttribute('class','info');
info.textContent = this.getAttribute('text') || 'default';
const style = document.createElement('style')
style.textContent = `
span {
color: red;
}
`
// this.appendChild(info)
shadow.appendChild(style);
shadow.appendChild(info);
}
})
Вы можете попробовать добавить несколько тегов span в другом месте на странице, но вы обнаружите, что только следующие теги span действуют с красным стилем.
Вышеупомянутые два свойства могут создать настраиваемый элемент (т.е. веб-компонент), на который не влияет внешнее влияние, который имеет внутреннюю логику выполнения JS и имеет независимый CSS. Я думаю, все начали жаловаться, такое JQ-подобное письмо просто неоднородно, и его трудно исправить после того, как DOM усложнится. Так как собрать более сложный дом, неужели нет решения? Нет, тогда есть еще одно свойство, о котором необходимо упомянуть здесь.
Template & Slot
Элемент шаблона — это функция, которую всегда поддерживали браузеры. Содержимое шаблона не будет отображаться при отображении HTML на экране. Прежде чем его можно будет создать и отобразить на странице, необходимо получить шаблон с помощью Javascript.
Затем мы можем использовать шаблон как фрагмент контента, который можно сохранить в документе, а затем заполнить шаблонWeb-Component
изshadow dom
в. Или возьмите приведенный выше пример и измените его.
<template id="my-component">
<style>
span {
color: red;
}
</style>
<span class="info">
12312312
</span>
</template>
customElements.define('my-component', class extends HTMLElement {
constructor() {
super()
const template = document.getElementById('my-paragraph');
const templateContent = template.content.cloneNode(true);
const shadow = this
.attachShadow({mode: 'open'})
.appendChild(templateContent);
}
})
Таким образом, это означает что-то вроде Vue, но в чем недостаток?Свойство text может быть прочитано и заполнено в my-component раньше.span.infoВнутри, кажется, сейчас нет такой возможности.
В это время нам нужно попросить наш слот-слот сделать это
HTML
<slot>
элемент ,так какWeb ComponentsЧасть набора технологий, заполнитель в веб-компоненте. Позже этот заполнитель можно заполнить вашим собственным языком разметки, чтобы вы могли создать отдельное дерево DOM и объединить его с другими компонентами.
Слот идентифицируется атрибутом имени, а позиция размещения указывает на его позицию в шаблоне.Когда другой элемент определяет атрибут слота с тем же именем, этот элемент будет заменен в шаблоне. Давайте изменим пример выше
<!-- 使用 -->
<template id="my-component">
<style>
span {
color: red;
}
</style>
<span name="my-slot" class='info' >default</span>
</template>
<!-- 使用 -->
<my-component>
<span slot="my-slot">
12312312
</span>
</my-component>
customElements.define('my-component', class extends HTMLElement {
constructor() {
super()
const template = document.getElementById('my-paragraph');
const templateContent = template.content.cloneNode(true);
const shadow = this
.attachShadow({mode: 'open'})
.appendChild(templateContent);
}
})
Конечно, это только самое простое использование, но пока в основномWeb-Component
Вы даже начинаете. Общая сложность написания не слишком высока, но есть еще много мест, на которые стоит пожаловаться.(подробнее о веб-компонентах). Итак, давайте посмотримLit
Что ты сделал, ты можешь позволитьWeb-Component
стать более удобным
что сделал Лит
Посмотрите, что мы только что сказалиWeb-Component
Несколько недостатков в нем
-
Отзывчивый имеет только обратные вызовы и не может быть автоматически сопоставлен с пользовательским интерфейсом.
-
Без внутреннего состояния состояния состояние, поддерживаемое вами, не может напрямую отслеживать изменения.
-
Нет шаблонного синтаксиса (можно использовать слот и шаблон)
Будьте ясны, учитесьLit
В процессе можно считать, что понятия состояния нет (собственно под ним понимаются частные реактивные свойства), есть только имяreactive properties
свойства члена. Его можно просто понимать как состояние и реквизит.
Итак, теперь проблема становится
-
Как реагировать на изменения реактивных свойств и применять их к пользовательскому интерфейсу
-
Как исправить синтаксис шаблона
Lit использует две основные библиотеки для решения этой проблемы, а именно:lit-element
а такжеlit-html
Lit-html
lit-html
даLit
Основная логика , может быть понята какLiteral Html
, он создал еще один высокопроизводительный механизм HTML-шаблонов для потока символов, отличный от JSX.
Lit решил напрямую унаследовать проект LitHTML от Polymer и переименовал общую структуру в Lit.
мы знаемjsx
Является ли базовый слой, который необходимо скомпилировать в конечном итоге, илиcreateElement
… а такжеlit-html
не то же самое, оно основано наtagged template
, заставляя его работать в браузере без компиляции, иHTML Template
Комбинируя, как играть и как играть, способность расширения становится сильнее. Давайте расширим его.
lit-html
Предоставляет два основных методаrender
а такжеhtml
lit-html.html
html`<p>${content}</p>`
Это собственный синтаксис es6 -Строка шаблона с тегами(шаблон с тегами), не волшебство, функция html примет следующие параметры
type taggedFunc = (strings: string[], ...values: any[]) => any;
// 上边的那个段代码接收到的参数就是
// ['<p>', '</p'>], content
проходить черезlit-html
Украшение приведенного выше кода в конечном итоге создастTemplate Result
Объект в форме
declare class TemplateResult {
readonly strings: TemplateStringsArray;
readonly values: readonly unknown[];
readonly type: string; // html or svg
readonly processor: TemplateProcessor;
constructor(strings: TemplateStringsArray, values: readonly unknown[], type: string, processor: TemplateProcessor);
getHTML(): string;
getTemplateElement(): HTMLTemplateElement;
}
const templateResult = {
strings: ['<p>', '</p>'],
value: [content]
type: 'html'
}
Обратите внимание здесьgetHTML
а такжеgetTemplateElement
метод, эти два метода могут преобразовывать строки в<template>
Марк, который является шаблоном, упомянутым выше
const template = (title, content, className) => html`
<h1 class="${className}">${title}</h1>
<div>${content}</div>
`;
<template>
<h1 class$lit$=\"{{lit-7227407027270176}}\"><!--{{lit-7227407027270176}}--></h1>
<div><!--{{lit-7227407027270176}}--></div>
</template>
Чтобы кратко объяснить, этот процесс заключается в обработке данных в строках один за другим в соответствии с различными ситуациями.
-
Attribute
-
Node
-
Comment
Объединяется в полную строку, затем innerHTML вставляется в созданный тег шаблона. Q: Как отличить настоящие комментарии в коде?
lit-html.render
Теперь у нас есть то, что мы проходим через шаблон меткиTemplateResult
(чистый объект-значение), рядом с вызовомrender
метод рендеринга шаблона на страницу, сначала посмотрите на APIrender(templateResult, container, options?)
render
получитьtemplateResult实例
и рендеринг контейнера для завершения рендеринга, который делится на первый рендеринг и рендеринг обновления.
первый рендер
сначала создайтеNodePart
Object (унаследован от Part, под которым можно понимать контроллер конструктора ноды, это реализация ядра, расширять пока не будем, увидим позже), а затем вызватьNodePart
примерappendInto
метод, добавьте два в контейнер рендерингаcomment
, запись обоихcomment
цитаты. следовать заNodePart
положитDOM
отдать этим двоимcomment
середина
<div id="container"><!---><!---></div>
<!-- 他是使用comment作为占位符的。 -->
тогда позвонюpart.commit
метод, который отображает содержание в контейнер
Commit делится на несколько ситуаций
-
directive
-
примитивный
-
templateResult
-
node
-
Iterable
-
пустой
По прежней логике, первый раз точно попадет сразу вtemplateResult
Ветвь , логика здесь может быть просто описана следующим образом,
пройти черезFactory
,использоватьTemplateResult
Раздел шаблонов в строках создаетTemplate
Объект (промежуточный продукт)Factory
Здесь выполняется слой кэширования, если вы используетеTemplateResult
Если шаблон (строки) имеет существующий шаблон, используйте существующий шаблон напрямую, если нет, создайте его снова.
При последующих вызовах метода рендеринга тот же самый шаблон (значение строки точно такое же, как и при первом вызове) повторно используется для первого шаблона, который можно понимать как постоянное значение, определяемое во время компиляции, и только значение изменения массива.
export declare class Template {
readonly parts: TemplatePart[];
readonly element: HTMLTemplateElement;
}
export type TemplatePart = {
readonly type: 'node'; index: number;
} | {
readonly type: 'attribute';
index: number;
readonly name: string;
readonly strings: ReadonlyArray<string>;
};
-
Сначала используйте шаблон TemplateResult (строка), чтобы узнать, есть ли готовый шаблон, если да, то повторно используйте его напрямую
-
Если нет, проверьте, есть ли ссылка на template.join markerKey в шаблоне keyString (markKey означает lit-7227407027270176)
-
Если нет, создайте экземпляр шаблона и кэшируйте шаблон, используя шаблон и keyString.
Процесс кеширования не поясняется, если интересно, посмотрите сами
Template
Объект разбивается на части и элемент, элемент конвертируется из TemplateResult<template>
, часть частей, проходит<template>
(dom walker) при создании. Упрощенное понимание процесса обработки
-
Если это узел узла
- Определяем есть ли атрибут, а имя атрибута имеет специальную метку, если да, то убираем атрибут на шаблоне, и пропихиваем его в деталь
{type: 'attribute', index, name, strings: statics}
структура, индекс — это индекс текущего обходчика, имя — имя атрибута, строки — символы до и после интерполяции этого атрибута
- Определяем есть ли атрибут, а имя атрибута имеет специальную метку, если да, то убираем атрибут на шаблоне, и пропихиваем его в деталь
-
Если это узел комментариев
-
Если содержание комментариев равен маркеру - (это можно отличить от реального комментария), затем нажимайте узел узла в деталь
{type: 'node', index}
- Если фронт - первый узел или узел уже является частью знака, сначала добавит пустой узел комментариев до текущего узла,
-
<template>
<h1 class$lit$=\"{{lit-7227407027270176}}\"><!--{{lit-7227407027270176}}--></h1>
<div><!--{{lit-7227407027270176}}--></div>
</template>
После обработки
{
element: template
parts: [
{type: "attribute", index: 1, name: "class", strings: ["", ""]},
{type: "node", index: 3},
{type: "node", index: 7},
]
}
// templatee也会会简化成如下结构
<template>
<h1><!----><!----></h1>
<div><!----><!----></div>
</template>
понятныйTemplate
является сформированнымDOM
шаблон, у него есть полныйDOM
и положение позиционирования, которое нужно интерполировать, но он еще не отрендерилсяDOM
начальство
Далее проверьте текущийTemplate
Был ли он созданTemplateInstance
экземпляр, если нет, создайте экземплярTemplateInstance
class TemplateInstance {
private readonly __parts;
readonly processor: TemplateProcessor;
readonly options: RenderOptions;
readonly template: Template;
constructor(template: Template, processor: TemplateProcessor, options: RenderOptions);
update(values: readonly unknown[]): void;
_clone(): DocumentFragment;
}
TemplateInstance пройдет<template>
Создайтеfragment
; затем повторитеparts
,согласно сTemplatePart
Литеральный тип, создайте экземпляры NodePart и AttributePart соответственно.
Последний вызовTemplateInstance
примерupdate
метод, который будет вызываться один за другимPart
примерsetValue
(истинное значение) иcommit
(метод рендеринга), в этот момент первый вызов метода рендеринга зацикливается, а остальные являются рекурсивными вызовами до тех пор, пока слой исходного типа значения не будет найден и отрендерен во фрагмент.
-
__commitText
: изменить текст текстового узла напрямую -
__commitNode
: Пустой родительский узел от startNode до endNode (наиболее упоминаемый в начале двух заполнителей комментариев), а затем добавьте в узел.
При возврате на верхний уровеньcommitNode
сделать это полнымfragment
, и поместите его в контейнер.
основной процесс
На данный момент завершен первый рендеринг, и общий процесс выглядит следующим образом
Это может показаться немного запутанным, мы можем пока игнорировать это.Template
, что является промежуточным состоянием
TemplateResult
похоже наJSX
Более легкое буквальное описание шаблона является модельTemplateInstance
можно понимать как небольшойMVC
вложение фреймов
-
DOM (фрагмент) — это внешняя структура приложения и постоянная часть представления.
-
TemplateResult
Членыvalue
модель -
Вид и Модель связаны в Контроллере (Детали). Предоставляет метод обновления данных (setValue) и метод рендеринга в представлении (Commit).
обновление рендеринга
Его можно сравнить с кешем библиотеки во время выполнения SQL.Если структура SQL непротиворечива, существующая модель будет повторно использована. Послойное сравнение для проверки всех попаданий в кэш (сравните тип и структуру строки шаблона)
-
Если попадется, используйте существующий шаблон, найдите
TemplateInstance
изPart
,ПучокtemplateResult
изvalue
обновить доPart
-
Если хита нет, переходим к первому процессу рендеринга
эффективность
-
带标签的模版字符串
выполнять по сравнению сJSX
будет более эффективным.JSX
Каждый рендер требует полного построения виртуального DOM, иlit-html
, он просто перестраивает очень легкий объект TemplateResult, и изменяется только набор значений. -
Процесс от TemplateResult до заключается в построении html непосредственно из TemplateResult, а затем использовании template.innerHTML для завершения синтаксического анализа. Этот процесс полностью выполняется с помощью собственного синтаксического анализатора браузера. Из-за использования технологии шаблонов этот DOM является фрагментом, а не частью реального DOM, и имеет небольшой объем памяти.
-
Фактический рендеринг DOM создается из template.importNode для завершения копии DOM. Вместо того, чтобы создавать один за другим узлы Dom, такие как React. Для больших DOM эффективность значительна.
-
В процессе инкрементного обновления Lit и React схожи тем, что повторно используются по одному и тому же уровню узлов.
diff(VDOM, DOM)
Для достижения инкрементного обновления LitHtml не использует алгоритм diff, а на основе рендеринга одного и того же шаблона необходимо обновлять только динамическую часть. Будет легче без алгоритма diff
Студенты, которые обратили внимание на статус Youda, возможно, видели, как что-то выходит, когда Vue 3 выпущен, vue-lit, vue-lit основан на механизме шаблонов lit-html и привязке данных @vue/reactivity Игрушка, созданная для будущего . Сам Lit также предоставляет пакет привязки данных, реагирующий на данные, для поддержки всей инфраструктуры.
Lit-element
Хорошо, синтаксис шаблона доступен, остальное — как применить изменение состояния в ответ на шаблон.
как использовать
Эта часть на самом деле несложная.Учащиеся, имеющие опыт разработки Vue, должны знать, как Vue связывает данные и представления.Lit-element
тоже так
В Lit вам нужно объявить такой компонент
@customElement('simple-greeting')
export class SimpleGreeting extends LitElement { /* ..*/ }
customElement на самом деле является синтаксическим сахаром для customElement.defined , аLitElement
даLit
Предоставляет базовый класс, в котором обрабатывается реактивная обработка данных (фактическиLitElement
также унаследовалUpdateElement
,Зависит отUpdateElement
Отвечайте на обработку).
Reactivity Property
Давайте сначала посмотрим, как определить требования в документации Lit.reactivity property
class MyElement extends LitElement {
@property()
name: string;
}
Мы обнаружим, что если нам нужны адаптивные свойства, нам нужно использовать декоратор свойств для оформления свойства.Логика декоратора свойств заключается в вызове статического метода класса, которому он принадлежит.createProperty
статический член класса_classProperties
Зарегистрируйте это свойство в , а заодно добавьте к этому свойству геттер и сеттер На этом подготовка класса завершена.
-
геттер: взять напрямую
-
setter: запускать обновление после обновления
Каждый раз, когда он изменяется внутри компонентаreactive property
Когда обновление свойства будет завершено, оно будет вызвано снова.lit-html
Метод рендеринга отображает пользовательский интерфейс.
Это очень похоже на понятие государства, тогдаlit-element
И как обрабатывать изменения внешних свойств транспорта (props)?
Здесь нам нужно применить ранее упомянутоеWeb-Component
жизненный циклget observedAttributes
а такжеattributeChangedCallback
. Эти два цикла запускаются каждый раз, когда свойство, переданное компоненту, изменяется, и вам нужно только запросить, находится ли оно в_classProperties
, и активно обновлятьreactive property
Вот и все.
Кроме того, декоратор свойств также может принимать параметры для настройки некоторых свойств для адаптации.
-
атрибут - определяет, привязана ли эта переменная-член к атрибуту элемента
-
конвертер - определяет логику преобразования из атрибутов элемента (обе строки) в реальные атрибуты
-
hasChanged — определяет, изменилось ли свойство
-
type - используется, когда конвертер не определен, преобразует тип элемента
-
Состояние — если состояние определено, эта переменная-член является внутренним состоянием, которое является частной, новой версией.
Lit
Для переопределения этого свойства предоставляется отдельный декоратор @state.
Lit
Остальные, такие как декораторы, привязки событий и т. д., не будут прорабатываться.Заинтересованные студенты могут прочитать исходный код, который намного читабельнее, чем React (Doge). На этом этапе завершена полная и ориентированная на будущее интерфейсная структура.
резюме
Lit
Поскольку вопросы совместимости не могут быть применены к реальным бизнес-сценариям, эта структура действительно достойна внимания и изучения. Некоторые из этих дизайнерских идей и концепций выходят за рамки ограничений React и дают другое возможное решение для интерфейсной среды. Нехорошо иметь доминирующее положение в области фреймворков, только с большей прихотью и охватом будущего развитие фронтенда может быть шире.
Также есть проблема, которую нельзя применить в реальных сценариях: Lit все еще находится в стадии быстрой итерации, и каждый раз это большие переломные изменения. Например, только что упомянутый элемент UpdateElement был разделен на отдельный пакет. . . .