คลาสพื้นฐานสำหรับการสร้างส่วนประกอบเว็บโดยใช้ LIT-HTML
lit-element สามารถติดตั้งผ่านแพ็คเกจ NPM LIT-HTML
lit-element ช่วยให้คุณสร้างส่วนประกอบของเว็บด้วยเทมเพลต HTML ที่แสดงด้วยตัวอักษรเทมเพลต JavaScript และแสดงผลอย่างมีประสิทธิภาพและ แสดงเทมเพลตเหล่านั้นอีกครั้ง ให้กับ DOM
lit-element ประสบความสำเร็จโดยการรวม LIT-HTML และมีคุณสมบัติดังต่อไปนี้:
render()renderCallbackinvalidate()this หรือการทำลายโครงสร้างid ใน Shadow Root โดยใช้ this.$(...)การสาธิตสามารถพบได้ที่นี่
เขียนโค้ด HTML ของคุณอย่างง่ายโดยใช้ lit-html โดยการสร้างวิธี render()
import { LitElement , html } from '/src/lit-element.js' ;
class HelloWorld extends LitElement {
render ( ) {
return html `
< div style =" font-weight: bold " > Hello World </ div >
` ;
}
}
customElements . define ( 'hello-world' , HelloWorld ) < hello-world > </ hello-world >id หลังจากเนื้อหาได้รับการแสดงผลครั้งแรก (เช่นหลังจาก FIRES connectedCallback() ไฟ) จากนั้นคุณสามารถเข้าถึงองค์ประกอบใน Shadow Root โดย id โดยใช้ this.$(...)
ในตัวอย่างด้านล่างเราเรียก this.changeColor() เมื่อใดก็ตามที่กดปุ่มซึ่งในผลลัพธ์จะเข้าถึง DIV โดยใช้ this.$("wrapper") และปรับเปลี่ยนสีพื้นหลังของมัน
class ColorMarker extends LitElement {
changeColor ( ) {
const color = Math . random ( ) . toString ( 16 ) . substr ( 2 , 6 ) ;
// Easily query the element by id:
this . $ ( "wrapper" ) . style . backgroundColor = `# ${ color } ` ;
}
render ( ) {
return html `
< style >
div {
background-color: yellow;
}
</ style >
< button on-click = ${ ( ) => this . changeColor ( ) } >
Change background color
</ button >
< div id =" wrapper " > < slot > </ slot > </ div >
` ;
}
}
customElements . define ( 'color-marker' , ColorMarker ) ; < color-marker > Horse </ color-marker > ในตัวอย่างนี้เราจะใช้คุณสมบัติ ทุกคุณสมบัติที่กำหนดไว้ใน properties() จะทำให้แน่ใจว่าเนื้อหาจะแสดงผลอีกครั้งในเวลาที่เหมาะสมเมื่อแก้ไข
คุณสมบัติสามารถมีค่าเริ่มต้นและสามารถสะท้อนผ่านแอตทริบิวต์ (การเปลี่ยนแปลงไปทั้งสองวิธี) แทนที่จะทำเวทมนตร์และการแปลงกรณีหลังจากกฎพิเศษเช่น upper-case กับ upperCase คุณแทนที่จะกำหนดตัวอย่างที่คุณลักษณะชื่อคุณสมบัติควรสะท้อนให้เห็นและหลีกเลี่ยงความกำกวมใด ๆ
หมายเหตุเมื่อใช้คุณสมบัติคุณต้องเรียก this.withProperties ก่อนใช้องค์ประกอบ เมื่อวิธีการส่งคืนคลาสนั้นสามารถทำได้เป็นส่วนหนึ่งของ customElements.define(...)
หมายเหตุค่าเริ่มต้นของแอตทริบิวต์จะถูกตั้งค่าจากแอตทริบิวต์องค์ประกอบเอง (ปัจจุบันหรือขาดหายไป) และค่าเริ่มต้นที่ตั้งค่าผ่าน 'ค่า' จะถูกละเว้น
import { LitElement , html } from '/src/lit-element.js' ;
class HelloWorld extends LitElement {
static get properties ( ) {
return {
uppercase : {
type : Boolean ,
attrName : "uppercase"
}
}
}
render ( ) {
return html `
< style >
.uppercase {
text-transform: uppercase;
}
</ style >
< div id =" box " class$ =" ${ this . uppercase ? 'uppercase' : '' } " >
< slot > Hello World </ slot >
</ div >
` ;
}
}
customElements . define ( 'hello-world' , HelloWorld . withProperties ( ) ) ; < hello-world > </ hello-world >
< hello-world uppercase > ¡Hola, mundo! </ hello-world > เมื่อสร้างองค์ประกอบที่กำหนดเองรูปแบบที่ดีคือการใช้แอตทริบิวต์แทนวิธีการหรือคุณสมบัติ สิ่งนี้ช่วยให้การใช้องค์ประกอบที่ประกาศเช่น <my-dialog opened>
สำหรับองค์ประกอบที่กำหนดเองที่บริโภคภายในในองค์ประกอบที่กำหนดเองอื่น ๆ เท่านั้นมันมักจะเร็วขึ้นเพียงแค่พึ่งพาคุณสมบัติ นี่เป็นกรณีนี้หากคุณต้องการส่งผ่านข้อมูลที่ซับซ้อนเช่นอาร์เรย์หรือวัตถุ
เพื่อให้ง่ายต่อการทำงานกับแอตทริบิวต์ lit-html-element รองรับการแมประหว่างแอตทริบิวต์และคุณสมบัติโดยอัตโนมัติเพียงแค่กำหนดชื่อของแอตทริบิวต์คุณสมบัติควรทำแผนที่ด้วย attrName:
การมีอยู่ของแอตทริบิวต์หรือไม่ (ในองค์ประกอบ) ส่งผลให้ ค่าจริง เช่น แอตทริบิวต์ที่ขาดหายไปสำหรับคุณสมบัติบูลีนหมายความว่าคุณสมบัติจะเป็น false และสำหรับประเภทคุณสมบัติอื่น ๆ ทั้งหมด undefined ซึ่งหมายความว่าเมื่อการแมปคุณสมบัติไปยังแอตทริบิวต์ไม่มีสิ่งใดเป็นค่าเริ่มต้นเนื่องจากค่าจะถูกกำหนดไว้เสมอขึ้นอยู่กับการมีอยู่หรือไม่ของแอตทริบิวต์ ซึ่งหมายความว่า value: ถูกละเว้นเมื่อ attrName: มีอยู่
ค่าจะถูกแปลงโดยใช้ตัวสร้างประเภทของพวกเขาเช่น String(attributeValue) สำหรับ String Number(attributeValue) สำหรับ Number ฯลฯ
Boolean มีการจัดการพิเศษเพื่อทำตามรูปแบบของแพลตฟอร์มเว็บ
จากมาตรฐาน HTML:
การมีอยู่ของแอตทริบิวต์บูลีนบนองค์ประกอบแสดงถึงค่าที่แท้จริงและการขาดแอตทริบิวต์แสดงถึงค่าเท็จ
หากแอตทริบิวต์มีอยู่ค่าของมันจะต้องเป็นสตริงที่ว่างเปล่าหรือค่าที่เป็นการจับคู่ตัวพิมพ์ใหญ่ ASCII สำหรับชื่อที่เป็นที่ยอมรับของแอตทริบิวต์โดยไม่มีช่องว่างชั้นนำหรือต่อท้าย
Array และ Object ถูกแยกออกจากคุณลักษณะและไม่มีการจัดการพิเศษดังนั้นค่าจะถูกแปลงโดยใช้ตัวสร้างเป็นประเภทอื่น ๆ ยกเว้นบูลีน
this ส่งผ่านไปยัง Render () สำหรับคุณซึ่งสะอาดกว่า โดยเฉพาะอย่างยิ่งเมื่อมีการทำลายโครงสร้าง คุณยังสามารถอ้างอิงพวกเขาด้วยตนเองได้
class RenderShorthand extends LitElement {
static get properties ( ) {
return {
greeting : {
type : String ,
value : "Hello"
}
}
}
render ( { greeting } ) {
return html ` ${ greeting } World!` ;
}
}
customElements . define ( 'render-shorthand' , RenderShorthand . withProperties ( ) ) ; เมื่อคุณสมบัติใด ๆ ใน properties() เปลี่ยนแปลง lit-element จะทำให้เกิดขึ้นใหม่โดยอัตโนมัติ เช่นเดียวกันกับแอตทริบิวต์ที่แมปกับคุณสมบัติผ่าน attrName
หากคุณต้องการแสดงผลด้วยตนเองอีกครั้งคุณสามารถเรียกใช้การเรนเดอร์อีกครั้งผ่านการโทรเพื่อ invalidate() สิ่งนี้จะกำหนดเวลา microtask ซึ่งจะแสดงเนื้อหาก่อน requestAnimationFrame ถัดไป
องค์ประกอบที่กำหนดเองจะต้องได้รับการอัพเกรดก่อนที่จะทำงาน สิ่งนี้จะเกิดขึ้นโดยอัตโนมัติโดยเบราว์เซอร์เมื่อมีทรัพยากรทั้งหมดที่ต้องการ
ซึ่งหมายความว่าหากคุณทำองค์ประกอบที่กำหนดเองซึ่งขึ้นอยู่กับองค์ประกอบที่กำหนดเองอื่น ๆ และใช้คุณสมบัติสำหรับการไหลของข้อมูลจากนั้นการตั้งค่าคุณสมบัติเหล่านั้นก่อนที่องค์ประกอบจะได้รับการอัพเกรดหมายความว่าคุณจะจบลงด้วยคุณสมบัติ lit-html-element ซึ่งหมายความว่าการอัปเดตคุณสมบัติและการสะท้อนแอตทริบิวต์จะไม่ทำงาน
มี API whenAllDefined(result, container) สำหรับการทำงานกับปัญหานี้โดยอนุญาตให้รอจนกว่าการพึ่งพาทั้งหมดจะได้รับการอัพเกรด วิธีหนึ่งในการใช้มันคือการเขียนทับ renderCallback() :
renderCallback ( ) {
if ( "resolved" in this ) {
super . renderCallback ( ) ;
} else {
whenAllDefined ( this . render ( this ) ) . then ( ( ) => {
this . resolved = true ;
this . renderCallback ( ) ;
} ) ;
}
}แต่คุณอาจยังคงจัดการกับคุณสมบัติเงาหากคุณตั้งค่าด้วยตนเองก่อนที่จะอัพเกรดเช่น
document . getElementById ( 'ninja' ) . firstName = "Ninja" ;ดังนั้นปกป้องวิธีต่อไปนี้:
customElements . whenDefined ( 'computed-world' ) . then ( ( ) => {
document . getElementById ( 'ninja' ) . firstName = "Ninja" ;
} ) ;หากคุณต้องการคุณสมบัติบางอย่างที่คำนวณและอัปเดตขึ้นอยู่กับคุณสมบัติอื่น ๆ นั่นเป็นไปได้โดยใช้ค่า 'คำนวณ' ซึ่งกำหนดวิธีการวัตถุที่มีอาร์กิวเมนต์เป็นสตริง
คุณสมบัติที่คำนวณได้จะอัปเดต เฉพาะ เมื่อ มีการกำหนดคุณสมบัติขึ้นอยู่กับทั้งหมด ค่าเริ่มต้นสามารถตั้งค่าได้โดยใช้ value:
หมายเหตุคุณสมบัติที่คำนวณไม่สามารถสะท้อนให้เห็นถึงแอตทริบิวต์
เช่น
import { LitElement , html } from '/node_modules/lit-html-element/lit-element.js' ;
class ComputedWorld extends LitElement {
static get properties ( ) {
return {
firstName : {
type : String ,
attrName : "first-name"
} ,
doubleMessage : {
type : String ,
computed : 'computeDoubleMessage(message)'
} ,
message : {
type : String ,
computed : 'computeMessage(firstName)' ,
value : 'Hej Verden'
}
}
}
computeDoubleMessage ( message ) {
return message + " " + message ;
}
computeMessage ( firstName ) {
return `Konichiwa ${ firstName } ` ;
}
render ( ) {
return html `
< div style =" font-weight: bold " > ${ this . doubleMessage } </ div >
` ;
}
}
customElements . define ( 'computed-world' , ComputedWorld . withProperties ( ) ) < computed-world > </ computed-world >
< computed-world first-name =" Kenneth " > </ computed-world > เป็นไปได้ที่จะใช้ lit-html-element จาก typeScript แทน JavaScript เมื่อใช้ TypeScript คุณสามารถเลือกใช้งานตกแต่งแทนการกำหนดคุณสมบัติคงที่ accessor static get properties()
เมื่อใช้ผู้ตกแต่งคุณสมบัติผู้เข้ายึดทรัพย์สินคงที่ใด ๆ จะถูกละเว้นและคุณไม่จำเป็นต้องโทร .withProperties() เช่นกัน
import {
LitElement ,
html ,
TemplateResult ,
customElement ,
property ,
attribute ,
computed
} from '../../src/lit-element.js' ;
@ customElement ( 'test-element' )
export class TestElement extends LitElement {
@ computed ( 'firstName' , 'lastName' )
get fullName ( ) : string {
return ` ${ this . firstName } ${ this . lastName } ` ;
}
@ property ( ) firstName : string = 'John' ;
@ property ( ) lastName : string = 'Doe' ;
@ property ( ) human : boolean = true ;
@ property ( ) favorite : any = { fruit : 'pineapple' } ;
@ property ( ) kids : Array < string > = [ 'Peter' , 'Anna' ] ;
@ attribute ( 'mother' ) mother : string ;
@ attribute ( 'super-star' ) superStar : boolean ;
render ( ) : TemplateResult {
return html `
< h2 > Name: ${ this . fullName } </ h2 >
< h2 > Is human?: ${ human ? "yup" : "nope" } </ h2 >
< h2 > Favorites: ${ JSON . stringify ( this . favorite ) } </ h2 >
< h2 > Kids: ${ JSON . stringify ( this . kids ) } </ h2 >
< h2 > Mother: ' ${ this . mother } ' </ h2 >
< h2 > Superstar?: ' ${ this . superStar } ' </ h2 >
` ;
}
} < test-element super-star mother =" Jennifer " > </ test-element > ในการใช้งานตกแต่งจาก TypeScript คุณต้องเปิดใช้งานการตั้งค่าคอมไพเลอร์ experimentalDecorators ใน tsconfig.json ของคุณหรือใช้ --experimentalDecorators Flag
{
"compilerOptions" : {
"experimentalDecorators" : true
}
}ด้วยการเปิดใช้งานด้านบนคุณสามารถเริ่มใช้งานตกแต่ง แต่ต้องระบุประเภทข้อมูลด้วยตนเอง:
@ property ( { type : String } )
myProperty: string ;เนื่องจากประเภทมักจะเกิดขึ้นจากคุณสมบัติโดยเฉพาะอย่างยิ่งใน typescript ที่คุณกำหนดประเภทสิ่งนี้ให้ความรู้สึกเหมือนทำงานสองครั้ง โชคดีที่มีข้อเสนอข้อกำหนดใหม่ที่เรียกว่า Metadata Reflection ซึ่งมีจุดมุ่งหมายในการแก้ปัญหานี้ ข้อเสนอนี้ยังไม่ได้รับการเสนออย่างเป็นทางการต่อคณะทำงาน TC39 (กำหนดมาตรฐาน JavaScript) แต่มีการใช้งานโพลีฟิลที่ใช้งานได้แล้วและการสนับสนุนการทดลองใน TypeScript
เมื่อเปิดใช้งานการสะท้อนข้อมูลเมตาดาต้าเป็นไปได้ที่จะกำหนดประเภทคุณสมบัติให้มากขึ้นอย่างรัดกุม:
@ property ( ) myProperty: string ;เพื่อที่จะใช้นักตกแต่งจาก TypeScript ทำตามขั้นตอนต่อไปนี้
emitDecoratorMetadata ใน tsconfig.json ของคุณหรือใช้ธง --emitDecoratorMetadata ของคุณ {
"compilerOptions" : {
"emitDecoratorMetadata" : true
}
}$ npm install --save-dev rbuckton/reflect-metadata < script src =" /node_modules/reflect-metadata/Reflect.js " > </ script >เอกสาร API ต่อไปนี้ใช้ Web IDL
PropertyOptions PropertyOptions ใช้สำหรับการกำหนดค่าคุณสมบัติสำหรับองค์ประกอบที่กำหนดเอง ใน JavaScript คุณจำเป็นต้องใช้อุปกรณ์เสริมคุณสมบัติแบบคงที่ที่เรียกว่า properties ซึ่งส่งคืนวัตถุที่คุณสมบัติแต่ละคุณสมบัติของวัตถุนั้นมี PropertyOptions ที่เกี่ยวข้อง:
class {
static get properties ( ) {
return { selfDefinedObjectProperty : ... }
}
} พจนานุกรม PropertyOptions มีคุณสมบัติทางเลือก 4 ตัวแสดงด้านล่างในรูปแบบเว็บ IDL
typedef (BooleanConstructor or DateConstructor or NumberConstructor or StringConstructor or ArrayConstructor or ObjectConstructor) PropertyType ;
dictionary PropertyOptions {
attribute PropertyType type ;
attribute any value ;
attribute USVString attrName ;
attribute USVString computed ;
}type คุณสมบัติ type เป็นตัวเลือกเฉพาะเมื่อใช้งานตกแต่งและการสะท้อนข้อมูลเมตา
value คุณสมบัติ value กำหนดค่าเริ่มต้นสำหรับคุณสมบัติ ในกรณีของการแมปแอตทริบิวต์ / คุณสมบัติผ่าน attrName (ดูด้านล่าง) value จะถูกละเว้น เมื่อใช้งานตกแต่งค่าจะได้รับจากนิยามคุณสมบัติของตัวเอง:
@ property ( ) myProperty: string = "Hello World" ; attrName attrName กำหนดชื่อของแอตทริบิวต์ซึ่งควรสะท้อนให้เห็นด้วยคุณสมบัติและวิธีอื่น ๆ ด้วย attrName ค่าเริ่มต้นจะถูกละเว้นและกำหนดจากองค์ประกอบที่กำหนดเองแทนเช่น ขึ้นอยู่กับการมีอยู่หรือไม่ของคุณลักษณะ
ชื่อแอตทริบิวต์เป็นตัวอักษรละติน (AZ) รวมถึง '-' (ยัติภังค์) แอตทริบิวต์ทั้งหมดในองค์ประกอบ HTML ในเอกสาร HTML จะได้รับ ASCII-LowerCased โดยอัตโนมัติและ Hyphen เริ่มต้น ('-') จะถูกละเว้น
โปรดทราบว่าคุณลักษณะข้อมูลคือ แอตทริบิวต์ที่เริ่มต้นด้วย data- สามารถเข้าถึงได้เป็นคุณสมบัติโดยอัตโนมัติผ่าน element.dataset
เมื่อคุณสมบัติที่แม็พได้รับการตั้งค่าบนองค์ประกอบแอตทริบิวต์จะได้รับการอัปเดตด้วยการแสดงสตริงของค่าใหม่เว้นแต่ว่าค่าใหม่จะ undefined ซึ่งแอตทริบิวต์จะถูกลบออก
มีข้อยกเว้นอย่างหนึ่งสำหรับสิ่งนี้เนื่องจากคุณสมบัติบูลีนที่สะท้อนออกมาแตกต่างกัน การตั้งค่าคุณสมบัติเป็น true และแอตทริบิวต์ (Say attr ) ถูกตั้งค่าเป็นสตริงว่าง '' (หมายถึงแอตทริบิวต์มีอยู่เช่น <div attr> ) การตั้งค่าคุณสมบัติเป็น false และแอตทริบิวต์จะถูกลบออกคือ <div>
เมื่อตั้งค่าแอตทริบิวต์ค่าจะถูกแปลงโดยใช้ตัวสร้างประเภทของพวกเขาเช่น String(attributeValue) สำหรับ String Number(attributeValue) สำหรับ Number ฯลฯ
Boolean มีการจัดการพิเศษเพื่อทำตามรูปแบบของแพลตฟอร์มเว็บ
จากมาตรฐาน HTML:
การมีอยู่ของแอตทริบิวต์บูลีนบนองค์ประกอบแสดงถึงค่าที่แท้จริงและการขาดแอตทริบิวต์แสดงถึงค่าเท็จ
หากแอตทริบิวต์มีอยู่ค่าของมันจะต้องเป็นสตริงที่ว่างเปล่าหรือค่าที่เป็นการจับคู่ตัวพิมพ์ใหญ่ ASCII สำหรับชื่อที่เป็นที่ยอมรับของแอตทริบิวต์โดยไม่มีช่องว่างชั้นนำหรือต่อท้าย
อ่านเพิ่มเติมในส่วนการสะท้อนแอตทริบิวต์ด้านบน
computed คุณสมบัติสามารถคำนวณได้จากคุณสมบัติอื่น ๆ โดยใช้ computed ใช้สตริงเช่น 'methodName(property1, property2)' โดยที่ methodName เป็นวิธีการในองค์ประกอบและ property1 และ property2 ถูกกำหนดไว้
คุณสมบัติที่คำนวณได้จะอัปเดต เฉพาะ เมื่อ มีการกำหนดคุณสมบัติขึ้นอยู่กับทั้งหมด ค่าเริ่มต้นสามารถตั้งค่าได้โดยใช้ value:
หมายเหตุคุณสมบัติที่คำนวณไม่สามารถสะท้อนให้เห็นถึงแอตทริบิวต์
renderCallback renderCallback อนุญาตให้ใช้ตะขอที่กำหนดเองก่อนและหลังการแสดงผล
หากคุณต้องการทำงานพิเศษก่อนที่จะแสดงผลเช่นการตั้งค่าคุณสมบัติตามคุณสมบัติอื่น subclass สามารถแทนที่ renderCallback() เพื่อทำงานก่อนหรือหลังการเรียกคลาสฐาน render() รวมถึงการตั้งค่าคุณสมบัติขึ้นอยู่กับก่อนที่ render()
withProperties()สิ่งที่ต้องทำ:
render(HTMLElement this)TODO: ย้ายเอกสารที่นี่
async invalidate()TODO: ย้ายเอกสารที่นี่
$(DOMString id)TODO: ย้ายเอกสารที่นี่
whenAllDefined(TemplateResult result)TODO: ย้ายเอกสารที่นี่
@customElement(USVString tagname)มัณฑนากรในชั้นเรียนสำหรับการลงทะเบียนองค์ประกอบที่กำหนดเอง
@ customElement ( 'my-element' )
class extends HTMLElement {
...
}@property(optional PropertyOptions options) มัณฑนากรที่ให้บริการสำหรับการเชื่อมต่อกับระบบคุณสมบัติ lit-html-element
เมื่อใช้อ็ู ธ อสังหาริมทรัพย์คุณไม่จำเป็นต้องกำหนดคุณสมบัติคงที่ accessor static get properties()
เมื่อใช้ผู้ตกแต่งคุณสมบัติผู้เข้ายึดทรัพย์สินคงที่ใด ๆ จะถูกละเว้นและคุณไม่จำเป็นต้องโทร .withProperties() เช่นกัน
@ property ( { type : String } )
myProperty: string ;ตรวจสอบส่วนขยายสำหรับ TypeScript สำหรับข้อมูลเพิ่มเติม
@attribute(USVString attrName) มัณฑนากรที่มีคุณสมบัติสำหรับการเชื่อมต่อกับระบบคุณสมบัติ lit-html-element และเชื่อมโยงคุณสมบัติกับแอตทริบิวต์องค์ประกอบที่กำหนดเอง
ตรวจสอบคุณสมบัติ attrName สำหรับข้อมูลเพิ่มเติม
@computed(any dependency1, any dependency2, ...) มัณฑนากรที่ให้คุณสมบัติสำหรับการเชื่อมต่อกับระบบคุณสมบัติองค์ประกอบ lit-html-element และสร้างอสังหาริมทรัพย์ที่ถูกคำนวณโดยอัตโนมัติจากคุณสมบัติอื่น ๆ
ตรวจสอบคุณสมบัติ computed สำหรับข้อมูลเพิ่มเติม
@listen(USVString eventName, (USVString or EventTarget) target) นักตกแต่งวิธีการสำหรับการเพิ่มผู้ฟังเหตุการณ์ คุณสามารถใช้สตริงสำหรับเป้าหมายและจะค้นหาองค์ประกอบใน Shadowroot ด้วย id นั้น
ผู้ฟังเหตุการณ์จะถูกเพิ่มหลังจากการเรนเดอร์ครั้งแรกซึ่งสร้างเงา DOM