เอ็นจิ้นเทมเพลตเสมือนจริงขนาดเล็ก (512 ไบต์) สำหรับโครงการฝังตัว
| เช่น / ขอบ | Firefox | โครเมี่ยม | ซาฟารี | โอเปร่า | iOS Safari | โครเมี่ยมสำหรับ Android |
|---|---|---|---|---|---|---|
| ขอบ 14+ | 45+ | 49+ | 10+ | 37+ | 10.2+ | 55+ |
.dom ยืมแนวคิดบางอย่างจาก React.js (เช่นส่วนประกอบที่ใช้งานได้และ DOM เสมือนจริง) และพยายามทำซ้ำด้วยรอยเท้าที่เล็กที่สุดเท่าที่จะเป็นไปได้โดยใช้ประโยชน์จากคุณสมบัติ ES6 JavaScript
ทำไม เพราะด้วยห้องสมุดดังกล่าวคุณสามารถสร้าง GUIs ที่ทรงพลังในสภาพแวดล้อมที่แน่นหนาเช่นอุปกรณ์ IoT ที่ประหยัดแม้กระทั่งไบต์พิเศษจริง ๆ แล้ว!
เล็กโดยการออกแบบ : ห้องสมุดไม่ควรเกินขนาด 512 ไบต์ เป้าหมายไม่ได้มีเอ็นจิ้นเทมเพลตอื่น แต่จะมีคุณสมบัติมากที่สุดเท่าที่จะเป็นไปได้ใน 512 ไบต์ หากจำเป็นต้องมีคุณสมบัติใหม่จะต้องมีคุณสมบัติอื่น ๆ หรือต้องลดขอบเขต
สร้างขึ้นเพื่ออนาคต : ห้องสมุดกำลังใช้ประโยชน์จากข้อกำหนด ES6 อย่างมากซึ่งหมายความ ว่าไม่ได้ รับการสนับสนุนจากเบราว์เซอร์รุ่นเก่า ปัจจุบันได้รับการสนับสนุนโดย 90% ของเบราว์เซอร์ในตลาด แต่คาดว่าสิ่งนี้จะใกล้เคียงกับ 100% ภายในปีหน้า
ประกาศ : อธิบาย HTML DOM ของคุณในรูปแบบที่มีโครงสร้างเป็นธรรมชาติช่วยให้คุณสร้างอินเทอร์เฟซผู้ใช้ที่ทรงพลัง แต่อ่านได้
ส่วนประกอบที่มุ่งเน้น : เช่นเดียวกับ react.js, .dom ส่งเสริมการใช้ส่วนประกอบที่ใช้งานได้
"เขียนน้อยลง" ตัวเร่งความเร็ว : API ห้องสมุดได้รับการออกแบบมาโดยเฉพาะเพื่อให้มีชื่อฟังก์ชั่นสั้น ๆ และตัวเร่งความเร็วช่วยให้คุณสามารถอธิบายมุมมองของคุณด้วยรหัสน้อยลง
.dom คุณใช้ .dom ในโครงการของคุณหรือไม่? แยกที่เก็บนี้และเพิ่มของคุณในรายการ!
สำหรับรอยเท้าขั้นต่ำให้รวมถึง dotdom.min.js.gz (512b) ในโครงการของคุณ
< script src =" dotdom.min.js.gz " />อีกทางเลือกหนึ่งคุณสามารถรวมไลบรารีรุ่นเล็ก ๆ ก่อนที่สคริปต์ของคุณ เพียงแค่คัดลอกรหัส minified
หากคุณรู้ว่า React.js ตัวอย่างต่อไปนี้สามารถช่วยให้คุณเข้าใจว่า. domer primitives เกี่ยวข้องกับการตอบสนองอย่างไร
การแสดงผลโครงสร้าง DOM ที่ง่ายมาก
| ตอบโต้ | .dom |
|---|---|
ReactDOM . render (
React . createElement ( 'div' , null , 'Hello world' ) ,
document . body
) ; | R (
H ( 'div' , 'Hello world' ) ,
document . body
) |
การสร้างส่วนประกอบที่คุณสามารถผ่านคุณสมบัติ
| ตอบโต้ | .dom |
|---|---|
function Hello ( props ) {
return React . createElement (
'div' , null , `Hello ${ props . toWhat } `
) ;
}
ReactDOM . render (
React . createElement (
Hello , { toWhat : 'World' } , null
) ,
document . body
) ; | function Hello ( props ) {
return H ( 'div' , `Hello ${ props . toWhat } ` ) ;
}
R (
H ( Hello , { toWhat : 'World' } ) ,
document . body
) |
การสร้างส่วนประกอบที่สามารถรักษาสถานะของตนเองได้
| ตอบโต้ | .dom |
|---|---|
class Clickable extends React . Component {
constructor ( ) {
super ( ... arguments ) ;
this . state = {
clicks : 0
} ;
}
render ( ) {
const { clicks } = this . state ;
return React . createElement (
'button' , {
onClick ( ) {
this . setState ( { clicks : clicks + 1 } )
}
} , `Clicked ${ clicks } times`
) ;
}
}
ReactDOM . render (
React . createElement ( 'div' , null ,
React . createElement ( Clickable , null , null ) ,
React . createElement ( Clickable , null , null )
) ,
document . body
) ; | function Clickable ( props , state , setState ) {
const { clicks = 0 } = state ;
return H ( 'button' ,
{
onclick ( ) {
setState ( { clicks : clicks + 1 } )
}
} ,
`Clicked ${ clicks } times`
) ;
}
R (
H ( 'div' ,
H ( Clickable ) ,
H ( Clickable )
) ,
document . body
) |
ส่วนประกอบยังสามารถสมัครรับเหตุการณ์วงจรชีวิต:
| ตอบโต้ | .dom |
|---|---|
class WithLifeCycle extends React . Component {
constructor ( ) {
super ( ... arguments ) ;
this . state = {
mounted : "no"
} ;
}
componentDidMount ( ) {
this . setState ( { mounted : "yes" } )
}
render ( ) {
const { mounted } = this . state ;
return React . createElement (
'div' , null , `mounted = ${ mounted } `
) ;
}
}
ReactDOM . render (
React . createElement ( 'div' , null ,
React . createElement ( WithLifeCycle , null , null ) ,
) ,
document . body
) ; | function WithLifeCycle ( props , state , setState , hooks ) {
const { mounted = "no" } = state ;
hooks . m . push ( ( ) => {
setState ( { mounted : "yes" } )
} ) ;
return H ( 'div' ,
`mounted = ${ mounted } `
) ;
}
R (
H ( 'div' , H ( WithLifeCycle ) ) ,
document . body
) |
การอัปเดต Keyed เป็นคุณสมบัติการกระทบยอดที่มีประโยชน์จาก React ที่ช่วยให้เอ็นจิ้นการแสดงผลสามารถตัดสินใจได้อย่างชาญฉลาดเกี่ยวกับองค์ประกอบที่จะอัปเดต
กรณีที่มีประโยชน์อย่างยิ่งคือเมื่อคุณแสดงรายการองค์ประกอบแบบไดนามิก เนื่องจากเอ็นจิ้นการเรนเดอร์ไม่เข้าใจว่าองค์ประกอบ ใด มีการเปลี่ยนแปลงจึงจบลงด้วยการอัปเดตที่ไม่ถูกต้อง
เพื่อแก้ปัญหานี้เครื่องยนต์ VDOM ใช้คุณสมบัติ key ที่ระบุองค์ประกอบในต้นไม้โดยเฉพาะ อย่างไรก็ตาม .dom แก้ปัญหาโดยเก็บสำเนาสถานะองค์ประกอบในอินสแตนซ์องค์ประกอบ VDOM เอง
ซึ่งหมายความว่าคุณไม่ต้องการคุณสมบัติ key ใด ๆ เพียงตรวจสอบให้แน่ใจว่าคุณได้ส่งคืนอินสแตนซ์ VDOM เดียวกันเหมือนเดิม
หากคุณกำลังสร้างองค์ประกอบแบบไดนามิก (เช่นอาร์เรย์ขององค์ประกอบ VDOM) .dom อาจมีปัญหาในการตรวจจับลำดับการอัปเดตที่ถูกต้อง
| ตอบโต้ | .dom |
|---|---|
class Clickable extends React . Component {
constructor ( ) {
super ( ... arguments ) ;
this . state = {
clicks : 0
} ;
}
render ( ) {
const { clicks } = this . state ;
const { ket } = this . props ;
return React . createElement (
'button' , {
onClick ( ) {
this . setState ( { clicks : clicks + 1 } )
}
} , `clicks= ${ clicks } , key= ${ key } `
) ;
}
}
const list = [ "first" , "second" , "third" ] ;
const components = list . map ( key =>
React . createElement ( Clickable , { key } , null ) ;
ReactDOM . render (
React . createElement ( 'div' , null ,
components
) ,
document . body
) ; | function Clickable ( props , state , setState ) {
const { clicks = 0 } = state ;
const { key } = props ;
return H ( 'button' ,
{
onclick ( ) {
setState ( { clicks : clicks + 1 } )
}
} ,
`clicks= ${ clicks } , key= ${ key } `
) ;
}
const list = [ "first" , "second" , "third" ] ;
const components = list . map ( key =>
H ( Clickable , { key } ) ;
R (
H ( 'div' , components ) ,
document . body
) |
โปรดทราบว่าโซลูชันข้างต้นจะอัปเดตส่วนประกอบที่เป็นสถานะอย่างถูกต้องแม้ว่าคำสั่งซื้อของพวกเขาจะเปลี่ยนไป อย่างไรก็ตามหากคุณต้องการฟังก์ชั่นที่สมบูรณ์แบบเหมือนปฏิกิริยาที่อัปเดตแต่ละปุ่มคุณสามารถใช้ปลั๊กอิน Keyed
function Container ( props , state ) {
const { components } = props ;
// The function `K` accepts the component state and an array of components that
// contain the `key` property, and returns the same array of components, with their
// state correctly manipulated.
return H ( "div" , K ( state , components ) ) ;
} คุณสามารถสร้างโหนด VDOM RAW (unreconciled) (เช่นที่มีเนื้อหา HTML โดยพลการ) โดยการตั้งค่าคุณสมบัติ .r ของวัตถุ Hooks เป็นค่าความจริงใด ๆ
สิ่งนี้จะปิดใช้งานการกระทบยอดเพิ่มเติมกับโหนดเด็กและทำให้เนื้อหาของคุณคงอยู่
function Description ( props , state , setState , hooks ) {
const { html } = props ;
hooks . r = 1 ; // Enable raw mode
return H ( 'div' , {
innerHTML : html
} )
} R( VNode, DOMElement ) R ( H ( 'div' , 'Hello' ) , document . body )แสดงผลต้นไม้ VNode ที่กำหนดให้กับองค์ประกอบ DOM ที่กำหนด การอัปเดตเพิ่มเติมจากส่วนประกอบของรัฐจะเกิดขึ้นกับเด็กทันทีเท่านั้น
H( tagName | function, [properties], [children ...]) H ( 'tag' )
H ( 'tag' , { prop : "value" } )
H ( 'tag' , H ( 'child' ) )
H ( 'tag' , { prop : "value" } , H ( 'child' ) )
H ( Component , { prop : "value" } )สร้างองค์ประกอบ vnode หากสตริงถูกส่งผ่านเป็นอาร์กิวเมนต์แรกมันจะสร้างองค์ประกอบ HTML หากได้รับฟังก์ชั่นมันจะสร้างองค์ประกอบที่เป็นสถานะ
คุณสมบัติและเด็กเป็นทางเลือกและสามารถละเว้นได้
แทนที่จะเป็นชื่อแท็กคุณสามารถให้ฟังก์ชั่นที่ส่งคืน DOM เสมือนจริงตามตรรกะระดับสูงกว่า ฟังก์ชั่นดังกล่าวมีลายเซ็นต่อไปนี้:
const Component = ( props , state , setState , hooks ) {
// Return your Virtual DOM
return div ( ... )
} คุณสมบัติ props มีวัตถุคุณสมบัติตามที่กำหนดเมื่อสร้างส่วนประกอบ
state จะเริ่มต้นเป็นวัตถุที่ว่างเปล่า {} และอัปเดตโดยเรียกใช้เมธอด setState({ newState }) หลังจะกระตุ้นการอัปเดตเป็นส่วนประกอบและเป็นเด็ก
นอกจากนี้คุณยังสามารถกำหนดคุณสมบัติให้กับวัตถุ state ได้โดยตรงหากคุณไม่ต้องการทำให้เกิดการอัปเดต
วัตถุ hooks สามารถใช้งานได้เมื่อคุณต้องการลงทะเบียนตัวจัดการกับวิธีวัฏจักรชีวิตส่วนประกอบ
คล้ายกับ React ส่วนประกอบ. add มีวงจรชีวิต:
ในการเข้าถึงวิธีวัฏจักรชีวิตคุณต้องใช้อาร์กิวเมนต์ที่สี่ในฟังก์ชั่นส่วนประกอบของคุณ โดยเฉพาะอย่างยิ่งคุณต้องผลักดันฟังก์ชั่นการจัดการของคุณในฟิลด์ทั้งสองต่อไปนี้:
const Component = ( props , state , setState , hooks ) {
hooks . m . push ( ( domElement ) => {
// '.m' is called when the component is mounted
} ) ;
hooks . u . push ( ( ) => {
// `.u` is called when the component is unmounted
} ) ;
hooks . d . push ( ( domElement , previousDomElement ) => {
// `.d` is called when the component is updated
} ) ;
...
}tag( [properties], [children ...] ) const { div , span , a } = H ;
div ( 'hello' , span ( 'world' ) )
div ( 'click' , a ( { href : '#' } , 'Here' ) , 'to continue' ) ฟังก์ชั่นชวเลขสามารถสกัดเป็นคุณสมบัติจากฟังก์ชัน H ชวเลขดังกล่าวมีพฤติกรรมเหมือน H แต่ด้วยชื่อแท็กที่มีประชากรแล้ว
ขอแนะนำให้ใช้การกำหนดโครงสร้างการมอบหมายในช่วงเริ่มต้นของสคริปต์ของคุณเพื่อช่วยให้ JavaScript minifiers เพิ่มประสิทธิภาพผลลัพธ์เพิ่มเติม:
const {div, span, a, button} = H;
tag.class( [properties], [children ...] ) const { h1 , span , p } = H ;
h1 . short ( 'short header' , span . strong ( 'strong text' ) )
button . primary ( { onclick : handleClick } , 'Primary Action' )
p . bold . italic ( twitterPost ) แทนที่จะให้ className เป็นคุณสมบัติคุณสามารถใช้ช .className เลข
นี่เป็นเช่นเดียวกับการเรียก div({className: 'className'}) และอินเตอร์เฟสฟังก์ชันนั้นเหมือนกับด้านบน
หมายเหตุ: คุณสามารถเพิ่มคลาสมากกว่าหนึ่งคลาสได้โดยการเชื่อมต่อมากกว่าหนึ่ง .class กับแท็ก ตัวอย่างเช่น: div.foo.bar เหมือนกับ div({className: 'foo bar'})
เนื่องจากโฟกัสของโครงการมีขนาดเล็กจึงขาดการตรวจสอบสติ สิ่งนี้ทำให้เกิดข้อผิดพลาด ระวังให้มาก กับคำเตือนต่อไปนี้:
คุณไม่สามารถทริกเกอร์การอัปเดตด้วยการลบคุณสมบัติ คุณ ต้อง ตั้งค่าคุณสมบัติใหม่เป็นค่าว่างแทน ตัวอย่างเช่น:
// Wrong
R ( div ( { className : 'foo' } ) , document . body ) ;
R ( div ( { } ) , document . body ) ;
// Correct
R ( div ( { className : 'foo' } ) , document . body ) ;
R ( div ( { className : '' } ) , document . body ) ; คุณ ต้อง ไม่ใช้คุณสมบัติที่ชื่อ $ ในส่วนประกอบของคุณ การทำเช่นนั้นจะทำให้วัตถุคุณสมบัติได้รับการพิจารณาว่าเป็นโหนด DOM เสมือนจริงและจะนำไปสู่ผลลัพธ์ที่ไม่คาดคิด
// *NEVER* do this!
R ( H ( MyComponent , { $ : 'Foo' } ) , document . body ) K(state, components)ใน
plugin-keyed.min.js
มั่นใจได้ว่าสถานะของส่วนประกอบในรายการจะถูกซิงโครไนซ์ตามคุณสมบัติ key ของพวกเขา สิ่งนี้ช่วยให้คุณสามารถทำการอัปเดตคีย์ที่มีลักษณะคล้ายกันได้เช่น:
function ValueRenderer ( ... ) {
...
}
function MyComponent ( props , state ) {
const { values } = props ;
const components = values . map ( value => {
H ( ValueRenderer , {
key : value ,
value : value
} ) ;
} )
// Synchronize state of components, based on their key
return H ( 'div' , K ( state , components ) )
} คุณสนใจที่จะมีส่วนร่วมใน . dom ? คุณยินดีมากกว่า! เพียงให้แน่ใจว่าได้ปฏิบัติตามแนวทาง:
npm install
npm test && npm run build && ls -l dotdom.min.js.gz
หากการทดสอบผ่านและขนาดของ dotdom.min.js.gz มีขนาดเล็กกว่าหรือเท่ากับ 512 ไบต์ให้สร้างคำขอดึง มิฉะนั้นลดขอบเขตของคุณหรือคิดว่าการใช้งานอื่นเพื่อนำกลับมาเป็น 512 ไบต์
ตรวจสอบให้แน่ใจว่าได้แสดงความคิดเห็นรหัสของคุณอย่างถูกต้องเนื่องจากคุณอาจต้องแฮ็ค JavaScript สุดขั้ว Gudeliens มีดังต่อไปนี้:
/**
* Functions are commented as JSDoc blocks
*
* @param {VNode|Array<VNode>} vnodes - The node on an array of nodes to render
* ...
*/
global . R = render = (
vnodes , // Flat-code comments start on column 70 and
dom , // wrap after column 120.
/* Logical separations can be commented like this */
...ได้รับอนุญาตภายใต้ใบอนุญาต Apache เวอร์ชัน 2.0