
Social Media -Foto von Federico Bottos auf Unplash
Eine winzige Toolless -Bibliothek mit Tools enthalten. Live -Demo
Bitte stellen Sie Fragen im Repository für dedizierte Diskussionen, um der Community bei diesem Projekt zu helfen, ♥ zu wachsen
Inspiriert von Vue 3 " One Piece " bietet UCE-Template ein benutzerdefiniertes integriertes <template> Element, um Komponenten in einer VUE -Mode zu definieren.
< template is =" uce-template " >
< style scoped >
span { color: green }
</ style >
< the-green >
The < span > {{thing}} </ span > is green
</ the-green >
< script type =" module " >
export default {
setup ( ) {
return { thing : 'world' }
}
}
</ script >
</ template >Fügen Sie diese Bibliothek der Gleichung hinzu und sehen Sie sie an, um alle definierten Komponenten zu starten.
<template lazy> Komponente, um ihre Definition nur dann zu beheben, wenn sie live sind<custom-element shadow> Komponenten und optional Shadowed <style shadow> Stile@uce -Moduls, um reaktive UIs und mehr zu erstellenresolve(name, module) vorgebracht werden Während es vorgeschlagen wird, die CLI weltweit zu installieren, ist es aufgrund einer nicht-super-leichten Abhängigkeit jedoch immer noch ein npx Befehl weg:
# check all options and usage
npx uce-template --help
# works with files
npx uce-template my-component.html
# works with stdin
cat my-component.html | uce-templateDas war's, aber natürlich sollten wir sicher sein, dass das produzierte Layout immer noch wie erwartet funktioniert?
Jede Vorlage, die uce-template erweitert, muss mindestens ein benutzerdefiniertes Element enthalten, entweder regulär oder integriert: erweitert:
<!-- register regular-element -->
< template is =" uce-template " >
< regular-element >
regular
</ regular-element >
</ template >
<!-- register builtin-element as div -->
< template is =" uce-template " >
< div is =" builtin-element " >
builtin
</ div >
</ template > Jede Vorlage kann ein einzelnes <script> -Tag und/oder eine oder mehrere <style> Definitionen enthalten.
Wenn eine Komponente {{slot.name}} Definitionen enthält, werden Knoten aus dem lebenden HTML nach dem Aufbau der Komponente nach dem Live eingerichtet.
Sehen Sie dieses Live -Beispiel, um mehr zu verstehen.
Jede " Komponente " kann sich mit oder ohne ihren eigenen statischen oder dynamischen Inhalt definieren.
Solche Inhalte werden verwendet, um jedes benutzerdefinierte Element nach " montiert " (live) und pro jedem reaktiven Zustand zu rendern, aber nur , wenn die Vorlage nicht leer ist.
Alle dynamischen Teile müssen in {{dynamic}} Curly -Klammern eingewickelt werden, wie hier gezeigt:
< my-counter >
< button onclick = {{dec}} > - </ button >
< span > {{state.count}} </ span >
< button onclick = {{inc}} > + </ button >
</ my-counter > Die Referenzen state , dec und inc werden, falls vorhanden, über den Skriptknoten weitergegeben.
Immer wenn die Komponente wiedergegeben wird, wird ihr Update -Rückruf berufen, das das Element selbst als Kontext bereitstellt.
< button is =" my-button " >
I am a {{this.tagName}}
</ button >In Bezug auf Shadowdom ist seine Polyfill nicht in diesem Projekt enthalten, aber es ist möglich, eine Komponente durch ihre Schattenwurzel zu definieren, indem ein Schattenattribut hinzugefügt wird:
< my-counter shadow >
<!-- this content will be in the shadowRoot -->
< button onclick = {{dec}} > - </ button >
< span > {{state.count}} </ span >
< button onclick = {{inc}} > + </ button >
</ my-counter > Das shadow ist standardmäßig open , kann aber auch als shadow=closed angegeben werden.
In Bezug auf {{JS}} , wenn Attribut, und Sie möchten {{ JS }} -Räume in der Nähe verwenden, muss das Attribut in Anführungszeichen enthalten sein, andernfalls durchbricht die HTML -Vorlage das Layout auf unerwartete Weise.
<!-- OK -->
< my-counter >
< button onClick = {{dec}} > - </ button >
</ my-counter >
<!-- OK -->
< my-counter >
< button onClick =" {{ dec }} " > - </ button >
</ my-counter >
<!-- IT BREAKS!!! -->
< my-counter >
< button onClick = {{ dec }} > - </ button >
</ my-counter ><!--{{interpolation}}--> FallDa hier alles hier hauptsächlich auf Standard -HTML -Verhaltensweisen basiert, gibt es Fälle, in denen eine Interpolation als Kommentar eingewickelt werden sollte.
Die Faustregel lautet: Wenn Sie das Layout nicht sehen oder einen schlechten Vorlagenfehler lesen, ist es möglich, dass Ihre Interpolation vom Vorlagenelement geschluckt worden sein könnte.
Dies geschieht hauptsächlich mit Elementen wie Tabelle , Auswahl und anderen Elementen, die nur einen bestimmten Typ des untergeordneten Knotens akzeptieren, jedoch nicht einen Text.
<!-- ? this won't work as expected -->
< table is =" my-table " >
< tbody > {{rows}} </ tbody >
</ table >
<!-- ? this works ? -->
< table is =" my-table " >
< tbody > <!--{{rows}}--> </ tbody >
</ table > Im ersten Fall würde der <tbody> einen Knoten ignorieren, der nicht eine <tr> außer für Kommentare ist, da Kommentare dabei nicht geschluckt oder verloren gehen.
Sie können die Definition dbmonster.html -Datei sowohl für die benutzerdefinierte <table> als auch für die benutzerdefinierte <tr> -Komponente sehen.
Eine Komponente kann in einem bestimmten Bereich einen oder mehrere Stile enthalten:
<style> wird seine Inhalte global anwenden, nützlich, um my-counter + my-counter {...} Fälle als Beispiel zu beheben<style scoped> wird seine mit dem benutzerdefinierten Elementnamen vorangestellten Inhalt anwenden (dh my-counter span, my-counter button {...} )<style shadow> wendet seinen Inhalt auf die Schattenwurzel an, vorausgesetzt, die Komponente ist mit einem shadow definiert Hier gibt es nichts Besonderes zu berücksichtigen, außer dass globale Stile den IE11 beeinträchtigen könnten, wenn es zu aufdringlich ist, da IE11 wieder den Zweck und das Verhalten der <template> -Element nicht versteht.
Eine Definition kann nur ein Skript -Tag enthalten, und ein solches Skript wird praktisch wie ein Modul behandelt.
Da IE11 nicht mit <template> Elementen kompatibel ist, versucht IE11 , alle Skripte auf der Seite rechts zu bewerten, wenn der type nicht angegeben ist.
Dementsprechend kann das type wirklich einen Wert haben, da es für diese Bibliothek völlig irrelevant ist, aber ein solcher Wert darf IE11 nicht kompatibel sein, und module ist nur ein Wert, den IE11 ignorieren würde.
Das Skript kann einen default export oder sogar ein module.exports = ... enthalten, wobei ein solcher Export möglicherweise über eine setup(element) { ... } Methode verfügt, die zurückgibt, was die dynamischen Teile der Komponente erwarten:
< script type =" module " >
import { reactive } from '@uce' ;
export default {
setup ( element ) {
const state = reactive ( { count : 0 } ) ;
const inc = ( ) => { state . count ++ } ;
const dec = ( ) => { state . count -- } ;
return { state , inc , dec } ;
}
} ;
</ script > Der @uce Reactive Helper ermöglicht es, die Ansicht automatisch zu aktualisieren, wenn sich eine seiner Eigenschaften ändert.
Um mehr über reaktive Veränderungen zu erfahren, lesen Sie bitte diesen mittleren Beitrag.
setup -Attribut Wenn ein <script type="module" setup> gefunden wird, wird der Inhalt des Skripts mit dem Element selbst als Kontext aufgerufen.
Live -Demo
< x-clock > </ x-clock >
< template is =" uce-template " >
< x-clock > {{time}} </ x-clock >
< script type =" module " setup >
let id = 0 ;
export default {
get time ( ) {
return ( new Date ) . toISOString ( ) ;
}
} ;
this . connected = e => id = setInterval ( this . render , 1000 / 30 ) ;
this . disconnected = e => clearInterval ( id ) ;
</ script >
</ template > Diese Verknüpfung ist speziell für Komponenten praktisch, die keine beobachteten ATTRIBUTS einrichten müssen, aber möglicherweise Requisiten einrichten müssen, und für den letzteren Fall sollte das setup -Attribut props enthalten.
< script type =" module " setup =" props " >
// props are defined as key => defaultValue pairs
export const props = {
name : this . name || 'anonymous' ,
age : + this . age || 0
} ;
</ script > Dieses Abschnittsziel ist es, grundlegende bis komplexe Beispiele über UCE-Template zu präsentieren, wobei einige Beispiele mit der Erweiterung .uce verwendet werden können, um Komponenten in ihren eigenen Dateien einzuschränken.
.uce Dateien als HTML an Wenn Sie VS -Code verwenden, können Sie Strg+Shift+P , Einstellungen JSON eingeben, die Einstellungen (JSON) auswählen und der folgenden Datei Folgendes hinzufügen, um die Dateien als HTML hervorzuheben .uce
{
"other-settings" : "..." ,
"files.associations" : {
"*.uce" : "html"
}
} Wenn wir Komponenten als view/my-component.uce definieren. Wir können uns genauso gut entscheiden, diese faul oder besser aufzunehmen, nur wenn diese auf der aktuellen Seite gefunden werden.
Dieser Ansatz vereinfacht viele Bündel, Abhängigkeiten, unnötige Aufblähern und kann durch Einbeziehung von nur uce-template und den winzigen (364 Bytes) UCE-Loader als Bootstrap durchgeführt werden, wobei schließlich zusätzliche Abhängigkeiten definiert werden, die über Komponenten hinweg verwendet werden.
import { parse , resolve } from 'uce-template' ;
import loader from 'uce-loader' ;
// optional components dependencies
import something from 'cool' ;
resolve ( 'cool' , something ) ;
// bootstrap the loader
loader ( {
on ( component ) {
// ignore uce-template itself
if ( component !== 'uce-template' )
fetch ( `view/ ${ component } .uce` )
. then ( body => body . text ( ) )
. then ( definition => {
document . body . appendChild (
parse ( definition )
) ;
} ) ;
}
} ) ;Die gleiche Technik könnte direkt auf jeder HTML -Seite verwendet werden, wobei auch Code geschrieben wird, die möglicherweise auch mit IE11 kompatibel sind.
<!doctype html >
< html >
< head >
< script defer src =" //unpkg.com/uce-template " > </ script >
< script defer src =" //unpkg.com/uce-loader " > </ script >
< script defer >
addEventListener (
'DOMContentLoaded' ,
function ( ) {
uceLoader ( {
Template : customElements . get ( 'uce-template' ) ,
on : function ( name ) {
if ( name !== 'uce-template' ) {
var xhr = new XMLHttpRequest ;
var Template = this . Template ;
xhr . open ( 'get' , name + '.uce' , true ) ;
xhr . send ( null ) ;
xhr . onload = function ( ) {
document . body . appendChild (
Template . from ( xhr . responseText )
) ;
} ;
}
}
} ) ;
} ,
{ once : true }
) ;
</ script >
</ head >
< body >
< my-component >
< p slot =" content " >
Some content to show in < code > my-component </ code >
</ p >
</ my-component >
</ body >
</ html >uce-templateWenn die meisten unserer Seiten keine Komponenten verwenden, kann das Hinzufügen von 7K+ JS auf jeder Seite unerwünscht sein.
Wir können jedoch den gleichen faul geladenen Komponentenansatz befolgen, außer dass unser Lader für die Einführung der UCE-Template -Bibliothek verantwortlich ist, entweder wenn ein UCE-Template selbst gefunden wird, oder in einer anderen Komponente.
import loader from 'uce-loader' ;
loader ( {
on ( component ) {
// first component found, load uce-template
if ( ! this . q ) {
this . q = [ component ] ;
const script = document . createElement ( 'script' ) ;
script . src = '//unpkg.com/uce-template' ;
document . body . appendChild ( script ) . onload = ( ) => {
// get the uce-template class to use its .from(...)
this . Template = customElements . get ( 'uce-template' ) ;
// load all queued components
for ( var q = this . q . splice ( 0 ) , i = 0 ; i < q . length ; i ++ )
this . on ( q [ i ] ) ;
} ;
}
// when uce-template is loaded
else if ( this . Template ) {
// ignore loading uce-template itself
if ( component !== 'uce-template' ) {
// load the component on demand
fetch ( `view/ ${ component } .uce` )
. then ( body => body . text ( ) )
. then ( definition => {
document . body . appendChild (
this . Template . from ( definition )
) ;
} ) ;
}
}
// if uce-template is not loaded yet
// add the component to the queue
else
this . q . push ( component ) ;
}
} ) ;Mit dieser Technik würde unsere JS -Nutzlast pro Seite jetzt auf weniger als 0,5 km reduziert, wenn der Code über den Code gebündelt und abgebrochen wird, während alles andere automatisch geschieht, wenn irgendwo auf der Seite Komponenten vorhanden sind.
Da die Seite andere benutzerdefinierte Elemente von Drittanbietern und Bibliotheken enthalten könnte, ist es möglicherweise eine gute Idee, einen bekannten Satz erwarteter Komponenten vorzulegen, um mögliche benutzerdefinierte Elemente über die Ansicht der view/${...}.uce -Anforderung zu laden.
Frühere faule Ladetechniken würden bereits in Ordnung funktionieren, aber anstatt zu überprüfen, ob der Komponentenname kein uce-template ist, könnten wir einen Satz verwenden:
loader ( {
known : new Set ( [ 'some-comp' , 'some-other' ] ) ,
on ( component ) {
if ( this . known . has ( component ) )
fetch ( `view/ ${ component } .uce` )
. then ( body => body . text ( ) )
. then ( definition => {
document . body . appendChild (
parse ( definition )
) ;
} ) ;
}
} ) ; Der Vorteil dieser Technik besteht darin, dass der known Satz durch die Liste der view/*.uce dynamisch generiert werden kann, damit nichts brechen würde, wenn die gefundene Komponente nicht Teil der UCE-Template- Familie ist.
uce-template muss unvermeidlich Function verwenden, um entweder Vorlagen-Teil- oder In-Script- Anforderungen (...) zu bewerten.
Es wird empfohlen, die Sicherheit zu erhöhen, indem sie entweder den Nonce ijeLM8+5uwZ7ZXFmK+H2dwIWdiKJ1A4zhZIsq2Ffqqo= oder das Integrity -Attribut über CSP -Skripte, die aus unserer eigenen Domäne stammen, vertrauen.
< meta http-equiv =" Content-Security-Policy " content =" script-src 'self' 'unsafe-eval' " >
< script defer src =" /js/uce-template.js "
integrity =" sha256-ijeLM8+5uwZ7ZXFmK+H2dwIWdiKJ1A4zhZIsq2Ffqqo= "
crossorigin =" anonymous " >
</ script >Bitte beachten Sie, dass sich diese Werte bei jeder Version ändern. Bitte stellen Sie sicher, dass Sie die neueste Version haben (diese Readme spiegelt die neueste).
Wenn die Definition für UCE ist, werden diese in onEvent(){...} Methoden enthält, diese werden verwendet, um die Komponente zu definieren.
Da die Staaten jedoch normalerweise von der Komponente selbst entkoppelt sind, ist es eine gute Idee, eine Schwächen zu verwenden, um eine Komponente mit ihrem Zustand in Beziehung zu setzen, und ... keine Sorge, Schwächen werden auch im IE11 nativ unterstützt!
Live -Demo
< button is =" my-btn " >
Clicked {{times}} times!
</ button >
< script type =" module " >
const states = new WeakMap ;
export default {
setup ( element ) {
const state = { times : 0 } ;
states . set ( element , state ) ;
return state ;
} ,
onClick ( ) {
states . get ( this ) . times ++ ;
// update the current view if the
// state is not reactive
this . render ( ) ;
}
} ;
</ script >Bitte beachten Sie, dass dieses Beispiel für den Anwendungsfall des Status -Komponenten -Gebrauchs abdeckt, da die Verwendung der Schwächen eine Empfehlung ist.
Wenn das props definiert ist und Requisiten * die Ansicht nach dem Ändern automatisch aktualisieren, benötigen wir möglicherweise keine Schwächen , um den Status der Komponente in Beziehung zu setzen.
Live -Demo
< button is =" my-btn " > </ button >
< template is =" uce-template " >
< button is =" my-btn " >
Clicked {{this.times}} times!
</ button >
< script type =" module " >
export default {
props : { times : 0 } ,
onClick ( ) {
this . times ++ ;
}
} ;
</ script >
</ template > Der Vorteil der Verwendung von Requisiten besteht darin, dass es möglich ist, einen Ausgangszustand durch Attribute zu definieren oder ihn direkt zu setzen, wenn er über das html -Dienstprogramm gerendert wird, sodass eine Schaltfläche mit times="3" wie beispielsweise dreimal angezeigt wird. sofort.
< button is =" my-btn " times =" 3 " > </ button > Der import {ref} from '@uce' Helfer vereinfacht das Abrufen des Knotens durch ref="name" Attribut.
< element-details >
< span ref =" name " > </ span >
< span ref =" description " > </ span >
</ element-details >
< template is =" uce-template " >
< element-details > </ element-details >
< script type =" module " setup >
import { ref } from '@uce' ;
const { name , description } = ref ( this ) ;
name . textContent = 'element name' ;
description . textContent = 'element description' ;
</ script >
</ template > Der import {slot} from '@uce' Helper vereinfacht das Abrufen von Slots mit Namen und gibt eine Reihe von Elementen zurück, die durch denselben Namen gruppiert sind.
Dies kann verwendet werden, um einzelne Slots in Interpolationen zu platzieren, wie in diesem Beispiel gezeigt, oder mehrere Slots innerhalb desselben Knotens platzieren.
Live -Demo
< filter-list >
Loading filter ...
< ul >
< li slot =" list " > some </ li >
< li slot =" list " > searchable </ li >
< li slot =" list " > text </ li >
</ ul >
</ filter-list >
< template is =" uce-template " >
< filter-list >
< div >
< input placeholder = filter oninput = {{filter}} >
</ div >
< ul >
{{list}}
</ ul >
</ filter-list >
< script type =" module " >
import { slot } from '@uce' ;
export default {
setup ( element ) {
const list = slot ( element ) . list || [ ] ;
return {
list ,
filter ( { currentTarget : { value } } ) {
for ( const li of list )
li . style . display =
li . textContent . includes ( value ) ? null : 'none' ;
}
} ;
}
} ;
</ script >
</ template >In Fällen , in denen die gleichnamige Slots-Reihenfolge nicht unbedingt nacheinander visualisiert wird, ist es immer möglich, stattdessen eine Reihe von Knoten zu übergeben.
Das heißt, jeder Interpolationswert kann ein DOM -Knoten, ein Wert oder ein Array von Knoten sein, wie µHTML funktioniert.
Live -Demo
< howto-tabs >
< p > Loading tabs ... </ p >
< howto-tab role =" heading " slot =" tab " > Tab 1 </ howto-tab >
< howto-panel role =" region " slot =" panel " > Content 1 </ howto-panel >
< howto-tab role =" heading " slot =" tab " > Tab 2 </ howto-tab >
< howto-panel role =" region " slot =" panel " > Content 2 </ howto-panel >
</ howto-tabs >
< template is =" uce-template " >
< howto-tabs >
{{tabs}}
</ howto-tabs >
< script type =" module " >
import { slot } from '@uce' ;
export default {
setup ( element ) {
const { tab , panel } = slot ( element ) ;
const tabs = tab . reduce (
( tabs , tab , i ) => tabs . concat ( tab , panel [ i ] ) ,
[ ]
) ;
return { tabs } ;
}
} ;
</ script >
</ template > Das von UCE-Template bereitgestellte Modulsystem ist extrem einfach und vollständig erweiterbar, sodass jede Komponente import any from 'thing'; Solange thing über die Bibliothek zur Verfügung gestellt/gelöst wurde.
Wenn wir einen einzelnen Bündel -Einstiegspunkt definieren wollen und wir wissen, dass jede Komponente eine oder mehrere Abhängigkeiten benötigt, können wir Folgendes tun:
import { resolve } from 'uce-template' ;
import moduleA from '3rd-party' ;
const moduleB = { any : 'value' } ;
resolve ( 'module-a' , moduleA ) ;
resolve ( 'module-b' , moduleB ) ;Sobald dieser Bau von Einstiegspunkten für einzelne Webseiten landet, können alle Komponenten alle Basis-/Standardmodule sowie alle vorauflösten sofort importieren .
Live -Demo (siehe sowohl HTML- als auch JS -Panel + Konsole)
< my-comp > </ my-comp >
< script type =" module " >
import moduleA from 'module-a' ;
import moduleB from 'module-a' ;
export default {
setup ( ) {
console . log ( moduleA , moduleB ) ;
}
}
</ script > Wenn die definierte Komponente etwas aus einer externen Datei wie import module from './js/module.js' importiert , würde ein solcher Import zusammen mit jedem anderen Modul, das noch nicht bekannt ist, faul gelöst werden, was bedeutet, dass ./js/module.js Datei eine solche enthalten könnte:
// a file used to bootstrap uce-template component
// dependencies can always use the uce-template class
const { resolve } = customElements . get ( 'uce-template' ) ;
// resolve one to many modules
resolve ( 'quite-big-module' , { ... } ) ;Ein Komponentenskript kann dann diese Datei importieren und gleich danach auf die exportierten Module zugreifen.
Live -Demo
< script type =" module " >
import './js/module.js' ;
import quiteBigModule from 'quite-big-module' ;
export default {
setup ( ) {
console . log ( quiteBigModule ) ;
}
}
</ script > Zusammen mit der faulen geladenen Komponente ermöglicht dieser Ansatz, Komponenten zu versenden, die vollständig auf einer externen vue/comp.uce -Dateidefinition basieren, wobei eine dieser Komponenten auch eine oder mehrere .js -Dateien freigeben kann, die in der Lage sind, jedes hier oder dort benötigte Modul zu beheben (freigegebene Abhängigkeiten in einer Datei, entgegengesetzt von Abhängigkeiten pro Lieferkomponenten).
Als eigenständige Datei liegt die Größe meiner benutzerdefinierten Elemente um 2,1 km , aber da es sich um fast jede Bibliothek handelt, die UCE auch verwendet, sah es nach dem besten Weg aus, um nur 1k mehr für ein Modul zu erreichen, das in etwa 7 km bis 10 km Budget passt.
Andererseits, da die Polyfill nicht aufdringlich ist und auf Erkennungen der Laufzeit basiert, bedeutet dies, dass sich niemand darum kümmert, dass ein anderes Polyfill jemals, sondern auch Chrom , Firefox und Rand unberührt wird, so dass jedes benutzerdefinierte Element nativ, entweder gebaut oder regelmäßig gebaut oder regelmäßig läuft.
Im Safari -Fall oder im Webkit basieren nur benutzerdefinierte Elemente, die in IE11 und in der alten MS Edge gebaut wurden, beide gebaute und reguläre Elemente werden gepatcht.
Das war's: Mach dir keine Sorgen um eine Polyfill, denn hier ist schon alles enthalten!
Wenn Sie auf Browser abzielen, von denen Sie wissen, dass sie bereits native benutzerdefinierte Elemente v1 angeben, können Sie diese ESM -Version verwenden, die alle Polyfills ausschließt und nur die Logik einbezieht.
Das aktuelle es.js -Bundle ist in der Tat ~ 7K GZIPPED und ~ 6,5K Brotli, so dass es möglich ist, auch zusätzliche Bandbreite in Ihrem Projekt zu sparen.
Nun, in diesem Fall muss das einzige Zielbrowser, das @WebReflection/Custom-Elements-gebaute Modul, vor dem UCE-Template -Modul auf der Seite enthalten sein.
< script defer src =" //unpkg.com/@webreflection/custom-elements-builtin " > </ script >
< script defer src =" //unpkg.com/uce-template " > </ script >Dadurch wird sichergestellt, dass sowohl reguläre als auch gebaute Erweiterungen wie erwartet funktionieren.
Leider ist Shadowdom eines dieser Spezifikationen, die es nicht zu Polyfill ist, aber die gute Nachricht ist, dass Sie selten Schatten in UCE-Template benötigen. Wenn Ihr Browser jedoch kompatibel ist, können Sie Shadowdom so viel verwenden, wie Sie möchten.
Es gibt jedoch mindestens zwei mögliche partielle Polyfills zu berücksichtigen: Attachshadow, das minimalistisch und leicht ist, und zwielichtig, was näher an Standards liegt, aber definitiv schwerer, obwohl beide Polyfills können und sollten, nur dann, wenn der aktuelle Browser es braucht, also den Code auf Ihre HTML -Seite mitbringen, um Schatten zu einem Schatten zu bringen.
<!-- this must be done before uce-template -->
< script >
if ( ! document . documentElement . attachShadow )
document . write ( '<script src="//unpkg.com/attachshadow"><x2fscript>' ) ;
</ script >
< script defer src =" //unpkg.com/uce-template " > </ script > Da jeder moderne Browser document.documentElement.attachShadow hat, wird das document.write nur in IE11 ohne Kompromisse eintreten oder mobile und moderne Desktop -Browser bestrafen.
PS Das <x2fscript> ist kein Tippfehler, sondern benötigt, um kein zerbrochenes Layout zu haben, das das Skript -Tag schließt
{{...}} anstelle von ${...} ? So sehr ich es auch geliebt hätte ${...} Interpolationsgrenzen zu haben, würde IE11 brechen, wenn ein Element im DOM ${...} als Attribut enthält.
Da {{...}} eine gut etablierte Alternative ist, habe ich beschlossen, mögliche IE11- Probleme zu vermeiden und einfach bei einer de-facto-Standardalternative zu bleiben.
Es lohnt sich auch zu bedenken, dass Vue auch {{...}} verwendet, ebenso wie viele andere vorlagenbasierte Motoren.
Function notwendig? Wie im Teil des Teils " CSP & Integrity/Nonce " der How -to/Beispiele erläutert, muss Function aus mindestens zwei Gründen verwendet werden:
"use strict"; Richtlinie und durch eine with(object) Anweisung bestehende Aussage, um Interpolationen zu verstehen, ohne einen ganzen JS -Engine vom Grund zu erstellen<script type="module"> Inhalt require Aber selbst wenn es in der Gleichung keine Function gäbe, wäre das Parsen und Ausführen eines <script> -Tags zum Definieren benutzerdefinierter Elemente genau das gleiche Äquivalent zur Verwendung Function gewesen, da CSP ohnehin spezielle Regeln benötigt hätte, da der Vorgang im Grunde genommen ein Eval -Aufruf im globalen Kontext ist.
Als Zusammenfassung habe ich, anstatt den Browser mit Praktiken oder als unsicher wie ein Function zu betreiben, einfach Function verwendet, um die Codegröße angemessen zu halten.
Dieses Projekt ist nach wie vor native benutzerdefinierte Elemente, mit Ausnahme der Definitionskosten, der eine einmalige Operation pro einzelner benutzerdefinierter Elementklasse ist, daher auf lange Sicht irrelevant , und es gibt einen unbedeutenden Overhead innerhalb der anfänglichen Vorlage an Parsen-Logik.
Sie können die klassische DBMonster -Demo hier überprüfen und sehen, dass sie einfach gut funktioniert.
Nichts in dieser Bibliothek blockiert und Module werden nur einmal aufgelöst, selbst relative Pfadimporte.
Die Logik ist ziemlich einfach: Wenn der Modulname nicht behoben wurde und es sich um einen relativen Import handelt, wird eine asynchrone Anfrage später gestellt und bewertet. Wenn das Modul nicht behoben ist und es sich um ein qualifizierter Name handelt, wird sie nur aufgelöst, sobald ein Code sie bereitstellt.
All dies und der Import für eine Lösung wird von dem UCE-Require-Helfer behandelt, der absichtlich nicht mit diesem Modul selbst verbunden ist, wie es hoffentlich auch von anderen Projekten inspirieren und auch von anderen Projekten verwendet werden könnte.
Wenn Sie mehr über uce-template verstehen möchten und wie es funktioniert, lesen Sie bitte diese Seite.