สร้างส่วนประกอบ UI ด้วย HTML ที่คุณมีอยู่แล้ว
2KB gzipped และ 6kb minified! -
data บางส่วนลงใน HTML ที่มีอยู่ของคุณ < div data-component =" Counter " >
< p data-bind =" state:Counter.count " > 0 </ p >
< button data-action =" click->Counter.decrement " >
-1
</ button >
< button data-action =" click->Counter.increment " >
+1
</ button >
</ div >class JavaScript? import { Component } from "domponent" ;
export default class Counter extends Component {
constructor ( el ) {
super ( el ) ;
}
increment ( ) {
this . setState ( { count : this . state . count + 1 } ) ;
}
decrement ( ) {
this . setState ( { count : this . state . count - 1 } ) ;
}
} import { Init } from "domponent" ;
import Counter from "./Counter.js" ;
const config = {
selector : document . getElementById ( "root" ) ,
components : {
Counter
} ,
appCreated : callbackFunction
} ;
new Init ( config ) ;แล้วคุณไปได้แล้ว !!
ห้องสมุดนี้ตั้งค่าวิธีที่สะอาดและทันสมัยในการเปลี่ยน HTML ที่เคยเป็นส่วนประกอบ UI คุณสามารถใช้การผูกมัดข้อมูลจัดการขอบเขตส่งข้อมูลรอบ ๆ และสร้างส่วนประกอบได้อย่างง่ายดายโดยใช้การประชุมบางอย่างในสคริปต์นี้ มันหมายถึงการเป็นทางเลือกที่มีน้ำหนักเบา มาก สำหรับการกระตุ้นด้วยรสชาติของปฏิกิริยา (วิธีการใช้ชีวิตอุปกรณ์ประกอบฉากและสถานะส่วนประกอบ)
Domponent ไม่จัดการกับการแสดงผลฝั่งไคลเอ็นต์นอกกรอบไม่ได้สร้าง DOM เสมือนไม่ได้แตกต่างกัน (แม้ว่าจะเป็นสถานะที่แตกต่างและอุปกรณ์ประกอบฉาก) มันไม่ได้หมายถึงการจัดการการกำหนดเส้นทางหรือสถานะแอปพลิเคชันทั้งหมด มันหมายถึงการใช้ชิ้นส่วน HTML (thymeleaf, ราง, ปั๊ก, เครื่องยนต์แม่แบบที่คุณใช้) และสร้างฟังก์ชันการใช้งานซ้ำได้ในรูปแบบของส่วนประกอบ
Domponent คล้ายกับการล้มลงในบางวิธี:
แตกต่างจาก knockoutjs, domponent:
การทำให้ล้มลง
HTML
< p > First name: < input data-bind =" value: firstName " /> </ p >
< p > Last name: < input data-bind =" value: lastName " /> </ p >
< h2 > Hello, < span data-bind =" text: fullName " > </ span > ! </ h2 >JS
var ViewModel = function ( first , last ) {
this . firstName = ko . observable ( first ) ;
this . lastName = ko . observable ( last ) ;
this . fullName = ko . pureComputed ( function ( ) {
return ` ${ this . firstName ( ) } ${ this . lastName ( ) } ` ;
} , this ) ;
} ;
ko . applyBindings ( new ViewModel ( "Planet" , "Earth" ) ) ;domponent
HTML
< div data-component =" Hello " data-state =" { " firstName ": "Planet", "lastName": "Earth"}" >
< p > First name: < input data-action =" input->Hello.setFirstName " /> </ p >
< p > Last name: < input data-action =" input->Hello.setLastName " /> </ p >
< h2 > Hello, < span data-bind =" state:Hello.fullName " > </ span > ! </ h2 >
</ div >JS
import { Component } from "domponent" ;
export default class Hello extends Component {
constructor ( conf ) {
super ( conf ) ;
}
setFirstName ( event ) {
this . setState ( { firstName : event . target . value } , ( ) => {
this . setFullName ( ) ;
} ) ;
}
setLastName ( event ) {
this . setState ( { lastName : event . target . value } , ( ) => {
this . setFullName ( ) ;
} ) ;
}
setFullName ( ) {
this . setState ( {
fullName : ` ${ this . state . firstName } ${ this . state . lastName } `
} ) ;
}
}https://tamb.github.io/domponent/
รายการสิ่งที่ต้องทำ: https://codesandbox.io/embed/domponent-todo-with-undo-redo-sp3s2?fontsize=14
การสาธิตท้องถิ่น
git clone repo นี้npm installnpm run build:html-dev หรือ npm run build:html-prod npm install -- save domponent คุณสามารถใช้เวอร์ชัน ES5 ได้โดยการนำเข้าไฟล์ domponent/dist/domponent.es5.production.min.js นี้
หากคุณไม่ได้ใช้ transpiler ขอแนะนำให้ใช้ ES5 UMD นี่คือลิงค์ JSDELVR:
// production
< script type = "text/javascript" src = "https://cdn.jsdelivr.net/npm/domponent@VERSION/dist/domponent.es5.production.min.js" defer > </ script >
// development
< script type = "text/javascript" src = "https://cdn.jsdelivr.net/npm/domponent@VERSION/dist/domponent.es5.development.min.js" defer > < / script > หมายเหตุ: ใช้ห้องสมุดนี้มากหรือน้อยเท่าที่คุณต้องการ คุณสามารถใช้สิ่งนี้สำหรับ data-component data-ref และ data-ref-array และทำให้การเลือก DOM ของคุณง่ายขึ้นมาก คุณสามารถสร้างส่วนประกอบไร้สัญชาติด้วยคลาส Exponent ท้องฟ้าเป็นขีด จำกัด ที่แกนกลางของมัน Domponent เป็นชุดของคลาสยูทิลิตี้สำหรับ HTML ของคุณ
data-component เราใช้เด็กเลวคนนี้เพื่อจับคู่ชื่อส่วนประกอบกับ class ที่สอดคล้องกันในวัตถุ Init configuration
ตัวอย่าง: หาก html ของคุณเป็น data-component="Counter" | คุณต้องมีส่วนประกอบในการกำหนดค่าที่เรียกว่า Counter
data-bind ผูก state หรือ props ฉากกับ textContent ขององค์ประกอบก่อนที่คุณจะระบุว่าคุณต้องการผูก state หรือ props data-bind="state:Counter.count" หรือ data-bind="props:Counter.count" ครึ่งซ้ายของ : บอกองค์ประกอบที่วัตถุที่จะผูกกับ (สถานะหรืออุปกรณ์ประกอบฉาก)
data-actionผูกเหตุการณ์ DOM ด้วยวิธีการส่วนประกอบ พิจารณาสิ่งต่อไปนี้:
< button data-action =" click->Counter.increment " >
+1
</ button > ครึ่งซ้ายของ : แสดงถึงสตริงตัวอักษรสำหรับเหตุการณ์ DOM ที่จะฟัง ครึ่งขวาสอดคล้องกับวิธีการส่วนประกอบ
หมายเหตุ: คุณสามารถเพิ่มผู้ฟังหลายคนด้วยท่อ | ตัวอย่าง:
< button data-action =" click->Counter.increment|mouseover->Counter.anotherMethod " >
+1
</ button > คุณสามารถผ่านตัวเลือก eventListener ได้เช่นกัน ตัวเลือกจะต้องเป็น . หลังจากวิธีการเรียน ตัวเลือกจะต้องคั่นด้วยเครื่องหมาย ,
< button
data-action =" click->Counter.increment.passive,capture|mouseover->Counter.anotherMethod.once,passive "
>
+1
</ button > data-state หากคุณต้องการสร้างอินสแตนซ์ส่วนประกอบของคุณด้วยสถานะเฉพาะ ในหน่วยความจำ คุณต้องแนบแอตทริบิวต์ data-state กับ องค์ประกอบรูท ของตัวอย่างส่วนประกอบ:
<div data-component="Counter" data-state='{"count":24, "isEven": true}'>
...
</div>
ถูกต้อง data-state ใช้วัตถุ JSON ที่ถูกต้อง
data-ref หากคุณต้องการอ้างอิงองค์ประกอบ DOM คุณสามารถใช้ data-ref ได้เช่นนั้น:
< div data-ref =" Counter.myElement " > </ div > คุณต้องนำองค์ประกอบใดองค์ประกอบเปิดอยู่ จากนั้นจะถูกเก็บไว้ในวัตถุส่วนประกอบ $refs
จากนั้นคุณสามารถเข้าถึงองค์ประกอบใน Counter โดยใช้ this.$refs.myElement ภายในอินสแตนซ์ส่วนประกอบ
data-ref-arrayคุณสามารถสร้างอาร์เรย์ขององค์ประกอบในองค์ประกอบของคุณด้วยวิธีนี้:
< div data-ref-array =" Counter.elements " > </ div >
< div data-ref-array =" Counter.elements " > </ div > จากนั้นจะถูกเก็บไว้ในวัตถุส่วนประกอบ $refs คุณสามารถเข้าถึงอาร์เรย์ขององค์ประกอบในองค์ประกอบของคุณด้วย this.$refs.elements
data-key นี่เป็นทางเลือกโดยสิ้นเชิง เป็นสตริง ที่ไม่ซ้ำกัน สำหรับ แต่ละ อินสแตนซ์ส่วนประกอบ
สิ่งนี้ถูกใช้ภายในเพื่อผูกอุปกรณ์ประกอบฉาก ดังนั้นคุณต้องรู้ $key ของส่วนประกอบที่คุณได้รับจากอุปกรณ์ประกอบฉาก
< div data-component =" Counter " data-key =" aUniqueKey " >
...
</ div >สมมติว่าคุณกำลังวนซ้ำสิ่งนี้ในภาษาเทมเพลตของคุณ คุณควรตรวจสอบให้แน่ใจว่ากุญแจของคุณไม่เหมือนใคร
# for (let i=0; i < 10 ; i++){
< div data-component =" Counter " key =" `aUniqueKey${i}` " > ... </ div >
} หากคุณไม่ได้ใช้แอตทริบิวต์นี้คีย์ที่ไม่ซ้ำกันจะถูกกำหนดให้กับแต่ละอินสแตนซ์ส่วนประกอบโดยอัตโนมัติ สามารถเข้าถึงได้ผ่าน this.$key
data-props คุณสามารถแบ่งปันสถานะจากองค์ประกอบหลักเป็น props ในองค์ประกอบเด็ก มาร์กอัปจะมีลักษณะเช่นนี้
< div data-component =" Counter " key =" parentCounter " >
< div
data-props =" myAwesomeProp<-parentCounter:ofFive "
data-component =" DisplayAnything "
> </ div >
</ div > ด้านซ้ายของลูกศร <- เป็นชื่อของเสาในส่วนประกอบ DisplayAnything ด้านขวาของลูกศรคือ $key ขององค์ประกอบหลัก, ลำไส้ใหญ่ : และชื่อของชิ้นส่วนของ state ที่จะสืบทอด
จากนั้นคุณสามารถใช้วิธี Lifecycle propsWillUpdate และ propsDidUpdate เพื่อทำการเปลี่ยนแปลงภายในองค์ประกอบลูกของคุณ
Component ?มาต่อกับเคาน์เตอร์กันเถอะ JS ขั้นต่ำที่จำเป็นในการสร้างส่วนประกอบด้านล่าง:
class Counter extends Component {
constructor ( conf ) {
super ( conf ) ;
}
} super เพิ่มวิธีการพื้นฐานและคุณสมบัติส่วนประกอบที่คุณต้องการ
อย่ากลายพันธุ์สถานะโดยตรง เรียก this.setState
setState ( stateObject , callbackFunction ) ;นี่เป็นแนวคิดที่คล้ายคลึงกับ setState ของ React - แม้ว่ามันจะถูกนำไปใช้แตกต่างกัน
คุณสามารถเพิ่มสถานะเริ่มต้นในองค์ประกอบ JS ของคุณและแทนที่ใน DOM
export default class Counter extends Component {
constructor ( conf ) {
super ( conf ) ;
this . state = {
count : parseInt ( this . state . count ) || 0 ,
isEven : this . state . count
? this . state . count % 2 === 0
? true
: false
: true ,
stateFieldFromDOM : this . state . stateFieldFromDOM || "default cat" ,
stateFieldDefault : "default iPhone 11"
} ;
this . setState ( this . state ) ;
} <div data-component="Counter" data-state="{"count": 4, "isEven":true, "stateFieldFromDOM": "some value here"}"
ฟิลด์สถานะข้างต้นจะแทนที่ฟิลด์สถานะ JS เริ่มต้น
ค่าที่มีผลผูกพันจาก setState จะเป็น textContent หากคุณต้องการใช้สถานะ/อุปกรณ์ประกอบฉากเพื่อแสดงผล HTML คุณสามารถเพิ่มผู้เฝ้าดูค่านั้นและอัปเดตโหนด $refs ที่จะเป็นที่ตั้งของ HTML ใหม่
watch ( ) {
return {
count : {
post ( newCount ) {
this . $refs . exclaimCount . innerHTML = `<div class="uppercase"> ${ newcount } !</div>` ;
}
}
}
}ต่อไปนี้เป็นวิธีการที่คุณสามารถใช้ในการเข้าถึงส่วนประกอบในจุดต่าง ๆ ในวงจรชีวิตของพวกเขา
| วิธีวงจรชีวิต | บริบท | คำอธิบาย |
|---|---|---|
| การเชื่อมต่อ | ส่วนประกอบ/เลขชี้กำลัง | ก่อนที่ห้องสมุดจะใช้ส่วนประกอบ/เลขชี้กำลังใด ๆ ของคุณและคุณสามารถเข้าถึงวิธีอื่น ๆ |
| ซึ่งเชื่อมต่อกัน | ส่วนประกอบ/เลขชี้กำลัง | หลังจากส่วนประกอบ/เลขชี้กำลังของคุณมีสายขึ้นและมีผู้จัดงานทั้งหมดเข้ามาแทนที่ |
| การตัดการเชื่อมต่อ | ส่วนประกอบ/เลขชี้กำลัง | ก่อนที่จะลบ EventListeners และการลบส่วนประกอบ/เลขชี้กำลังออกจากหน่วยความจำ |
| propswillupdate | ส่วนประกอบ/เลขชี้กำลัง | ก่อนที่อุปกรณ์ประกอบฉากจะได้รับการอัปเดตภายในองค์ประกอบของคุณจะไม่มีการกลายพันธุ์ของ DOM เกิดขึ้น |
| propsdidupdate | ส่วนประกอบ/เลขชี้กำลัง | หลังจากอุปกรณ์ประกอบฉากได้รับการอัปเดตแล้วและ DOM มีการเปลี่ยนแปลง |
| statewillupdate | ส่วนประกอบ | ก่อนสถานะขององค์ประกอบปัจจุบันหรืออุปกรณ์ประกอบฉากใด ๆ ของผู้อยู่ในความอุปการะเปลี่ยนไป |
| ระบุว่า | ส่วนประกอบ | ส่วนประกอบของเด็กที่มีอุปกรณ์ประกอบฉากที่สืบทอดมาได้ทำการจัดการ DOM และรัฐและอุปกรณ์ประกอบฉากได้เปลี่ยนไป |
คลาส Component และ Exponent มีวิธี watch ที่ต้องส่งคืนวัตถุ ผู้เฝ้าดูช่วยให้คุณสามารถเชื่อมต่อกับ state เฉพาะหรือ props เปลี่ยนค่าระหว่างส่วนประกอบ lifecyle สิ่งนี้จะช่วยให้ตรรกะของรัฐของคุณถูกแยกได้แทนที่จะเป็นกลุ่มทั้งหมดด้วย stateWillUpdate , stateDidUpdate , propsWillUpdate หรือ propsDidUpdate นี่คือการเลียนแบบผู้เฝ้าดูอย่างใกล้ชิดใน Vue.JS หมายเหตุ : อย่าตั้งชื่อ state ของคุณและ props ประกอบฉากเดียวกัน นี่คือการปฏิบัติที่ไม่ดีและจะทำลายนักดู
watch ( ) {
return {
myField : {
pre ( newValue , oldValue ) {
// my logic
} ,
post ( newValue ) {
// my logic
}
}
}
} คุณสามารถดูฟิลด์สถานะที่ดูได้ของคุณในส่วนประกอบ $watchers Object
ขยายคลาส Exponent เพื่อสร้างส่วนประกอบที่มี props เท่านั้น ซึ่งมีน้ำหนักเบากว่า Component เล็กน้อย เร็วกว่าในการลวดและใช้หน่วยความจำน้อยลง
import { Exponent } from 'domponent'
class StatelessThing extends Exponent{
constructor(conf){
super(conf);
}
}
จากนั้นคุณจะสามารถเข้าถึงได้เท่านั้น:
propsWillUpdatepropsDidUpdate ทำไม Exponent ??
เพราะมันตีความหรือ อธิบาย ข้อมูลที่ได้รับ ... และฟังดูเหมือนองค์ประกอบ
ส่วนประกอบหรือเลขชี้กำลังจะได้รับฟิลด์ต่อไปนี้
| ชื่อฟิลด์ | พิมพ์ | เข้าถึง | บริบท | คำอธิบาย |
|---|---|---|---|---|
| $ app | วัตถุ | สาธารณะ | ส่วนประกอบ/เลขชี้กำลัง | แอปพลิเคชัน Domponent ทั้งหมด |
| $ B | อาร์เรย์ | ส่วนตัว | ส่วนประกอบ/เลขชี้กำลัง | EventListener Bindings สำหรับการใช้งานภายใน |
| $ D | วัตถุ | ส่วนตัว | ส่วนประกอบ | ส่วนประกอบของผู้ปกครองอ้างอิงถึงเด็ก ๆ |
| $ คีย์ | สาย | สาธารณะ | ส่วนประกอบ/เลขชี้กำลัง | ตัวระบุที่ไม่ซ้ำกันสำหรับอินสแตนซ์ส่วนประกอบ |
| $ ชื่อ | สาย | สาธารณะ | ส่วนประกอบ/เลขชี้กำลัง | ชื่อของประเภทส่วนประกอบ |
| $ P | วัตถุ | ส่วนตัว | ส่วนประกอบ/เลขชี้กำลัง | คอลเลกชันภายในของอุปกรณ์ประกอบฉากและการอ้างอิง DOM |
| อุปกรณ์ประกอบฉาก | วัตถุ | สาธารณะ | ส่วนประกอบ/เลขชี้กำลัง | ข้อมูลคู่คีย์/ค่าผ่าน |
| $ root | องค์ประกอบ | สาธารณะ | ส่วนประกอบ/เลขชี้กำลัง | โหนดรูทโดมของส่วนประกอบ |
| $ S | วัตถุ | ส่วนตัว | ส่วนประกอบ | คอลเลกชันภายในของรัฐและการอ้างอิง DOM |
| สถานะ | วัตถุ | สาธารณะ | ส่วนประกอบ | คู่ข้อมูล/ค่าของข้อมูลที่สามารถอัปเดตได้ |
| $ watchers | วัตถุ | สาธารณะ | ส่วนประกอบ | ฟังก์ชั่นการเปลี่ยนแปลงที่เก็บไว้และคีย์สถานะและคีย์ที่เกี่ยวข้อง |
Init ? ฟังก์ชั่นนี้สร้างแอพและลงทะเบียนส่วนประกอบทั้งหมด สิ่งนี้ใช้วัตถุ config ตามอาร์กิวเมนต์ที่ต้องการ:
const config = {
selector : document . getElementById ( "root" ) ,
components : { Counter } ,
appCreated : callbackFunction
} ;
const App = new Init ( config ) ;จากนั้นจะเปิดเผยวิธีการต่อไปนี้:
และวัตถุต่อไปนี้:
นอกจากนี้คุณยังสามารถยกเว้นวัตถุ components ของการกำหนดค่าและสร้างแอพโดยไม่มีส่วนประกอบใด ๆ ที่จะเริ่มต้นด้วย
createComponent@params:
App . createComponent ( document . getElementById ( "added-html" ) , callback ) ; register@params
App . register ( NewComponent , callback ) ; deleteComponent@params:
data-key หรือเข้าถึงส่วนประกอบภายในผ่าน this.$key App . deleteComponent ( "my-component-instance-key" , callback ) ; unregister@params:
App . unregister ( "NewComponent" , callback ) ; เพื่อหลีกเลี่ยง data- แอตทริบิวต์การปะทะกับตัวเลือกอื่น ๆ ไลบรารี ฯลฯ คุณสามารถแทนที่ชื่อแอตทริบิวต์เริ่มต้นในวัตถุการกำหนดค่าแอป:
Init ( {
selector : getElementById ( 'root),
components : { Counter } ,
dataAttributes : {
component : 'mynamespace-component' ,
state : 'cool-state' ,
}
} ) ;ซึ่งหมายความว่า HTML ของคุณจะเป็นแบบนี้:
< div data-mynamespace-component =" Counter " data-cool-state =' {"count":12} ' >
...
</ div >คุณสามารถเลือกปรับแต่งไวยากรณ์ที่คุณใช้ใน HTML ของคุณ รายการต่อไปนี้สามารถปรับแต่งได้
INHERITS_FROM: '<-',
FROM_COMPONENT: '.',
KEY_VALUE: ':',
MULTIPLE_VALUES: "|",
METHOD_CALL: "->",
LIST: ","
ซึ่งหมายความว่าในการกำหนดค่าของคุณคุณสามารถเพิ่ม:
{
customSyntax : {
LIST : "!" ,
METHOD_CALL : "#"
}
}และ HTML ของคุณสามารถใช้สิ่งนี้ได้!
เมื่อพัฒนาด้วย domponent การใช้การพัฒนาจะเพิ่มข้อผิดพลาดที่เป็นประโยชน์และบันทึกไปยังคอนโซลของคุณจากการพัฒนา DOM (ผู้ชายคนนี้->)?
วิธีที่ง่ายที่สุดในการใช้งานนี้คือนามแฝง WebPack:
resolve : argv . mode === 'development' ? {
alias : {
domponent : 'domponent/dist/domponent.development.js'
}
} : { } ,วิธีนี้การพัฒนาของคุณสร้าง Webpack จะสลับเวอร์ชันการผลิตของ Domponent สำหรับเวอร์ชันที่โรยด้วยความช่วยเหลือจาก DOM
คุณสามารถเขียนส่วนประกอบ HTML ของคุณสำหรับเครื่องยนต์เทมเพลตต่างๆและ รวมไว้ เป็นส่วนหนึ่ง/ชิ้นส่วน/สิ่งที่เครื่องยนต์ของคุณอ้างถึงว่า "ชิ้นของ HTML"
นี่คือตัวอย่างของวิธีที่คุณอาจใช้ domponent
หมายเหตุ: แม้จะมีความแตกต่างทางไวยากรณ์เหล่านี้ในมาร์กอัปโปรดจำไว้ว่าส่วนประกอบนั้นเป็นเพียงคลาส JS ✌
ตัวอย่างไวยากรณ์ของปั๊ก ?
// counter.pug
mixin counter ( count )
div ( data - component = "Counter" data - state = `
{
"count": count,
"isEven": count % 2 === 0
}
` )
p ( data - bind = "state:Counter.count" ) # { count }
button ( data - action = "click->Counter.increment" ) + 1
button ( data - action = "click->Counter.decrement" ) - 1
// usage
+ counter ( 101119 )
+ counter ( 61316 )ตัวอย่างไวยากรณ์ Thymeleaf ?
// counter.html
< div
data-component =" Counter "
th:fragment =" Counter "
th:data-state =' |{"count":${count}, "isEven": ${count % 2 == 0}}| '
>
< p data-bind =" state:Counter.count " th:text =" ${count} " > </ p >
< button data-action =" click->Counter.increment " >
+1
</ button >
< button data-action =" click->Counter.decrement " >
-1
</ button >
</ div >
// usage
< th:block th:replace =" ./counter.html :: Counter(count: 1289) " />
< th:block th:replace =" ./counter.html :: Counter(count: 491) " />ตัวอย่างมีดโกนไวยากรณ์ ⚔เร็ว ๆ นี้ ...
Ruby on Rails ไวยากรณ์ตัวอย่าง ? เร็วๆ นี้...
ตัวอย่างไวยากรณ์หนวด ? เร็วๆ นี้...
domponent [at] gmail [dot] com ( โปรดใช้ Domponent Support เรื่องหรือเราจะไม่ตอบกลับ )@domponent