ส่วนประกอบที่ได้รับแรงบันดาลใจจากใบมีด Laravel สำหรับ postthtml
npm i -D posthtml-componentปลั๊กอิน PostTHTML นี้ให้ไวยากรณ์ที่เป็นมิตรกับ HTML สำหรับการใช้ส่วนประกอบในเทมเพลต HTML ของคุณ หากคุณคุ้นเคยกับ Blade, React, Vue หรือคล้ายกันคุณจะพบว่าไวยากรณ์ที่จะคุ้นเคยเนื่องจากปลั๊กอินนี้ได้รับแรงบันดาลใจจากพวกเขา
ดูเพิ่มเติมที่ PostTHTML Bootstrap UI โดยใช้ปลั๊กอินนี้และตรวจสอบเทมเพลตสตาร์ทเตอร์ที่นี่
| ชื่อ | พิมพ์ | ค่าเริ่มต้น | คำอธิบาย |
|---|---|---|---|
| ราก | String | './' | เส้นทางรูทที่จะมองหาส่วนประกอบ |
| โฟลเดอร์ | String[] | [''] | อาร์เรย์ของเส้นทางที่สัมพันธ์กับ options.root หรือเนมสเปซที่กำหนดไว้ |
| Fileextension | String|String[] | 'html' | ส่วนขยายไฟล์ส่วนประกอบเพื่อค้นหา |
| Tagprefix | String | 'x-' | แท็กคำนำหน้า |
| ติดแท็ก | String|Boolean | false | แท็กส่วนประกอบ ใช้กับ options.attribute บูลี false เท่านั้น |
| คุณลักษณะ | String | 'src' | แอตทริบิวต์ที่จะใช้สำหรับการกำหนดพา ธ ไปยังไฟล์ส่วนประกอบ |
| เนมสเปซ | String[] | [] | อาร์เรย์ของเส้นทางรูทเนมสเปซเส้นทางทางเลือกและเส้นทางแทนที่ที่กำหนดเอง |
| Namespacesperator | String | '::' | ตัวคั่นเนมสเปซสำหรับชื่อแท็ก |
| ผลผลิต | String | 'yield' | ชื่อแท็กสำหรับการฉีดเนื้อหาส่วนประกอบหลัก |
| ช่องเสียบ | String | 'slot' | ชื่อแท็กสำหรับสล็อต |
| เติม | String | 'fill' | ชื่อแท็กสำหรับการเติมช่อง |
| ผู้คัดเลือก | String | ':' | ตัวคั่นชื่อสำหรับ <slot> และ <fill> แท็ก |
| กองซ้อน | String | 'stack' | ชื่อแท็กสำหรับ <stack> |
| ดัน | String | 'push' | ชื่อแท็กสำหรับ <push> |
| propsscriptattribute | String | 'props' | แอตทริบิวต์ใน <script props> สำหรับการดึงอุปกรณ์ประกอบฉากส่วนประกอบ |
| propScontext | String | 'props' | ชื่อของวัตถุภายในสคริปต์สำหรับการประมวลผลอุปกรณ์ประกอบฉาก |
| Propsattribute | String | 'props' | ชื่อแอตทริบิวต์เพื่อกำหนดอุปกรณ์ประกอบฉากเป็น JSON บนแท็กส่วนประกอบ |
| Propsslot | String | 'props' | ใช้เพื่อดึงอุปกรณ์ประกอบฉากที่ส่งผ่านไปยังสล็อตผ่าน $slots.slotName.props |
| การแยกวิเคราะห์ | Object | {recognizeSelfClosing: true} | ตัวเลือกส่งผ่านไปยัง posthtml-parser |
| การแสดงออก | Object | {} | ตัวเลือกผ่านไปยัง posthtml-expressions |
| ปลั๊กอิน | Array | [] | ปลั๊กอิน PostTHTML เพื่อนำไปใช้กับทุกส่วนประกอบที่แยกวิเคราะห์ |
| ผู้จับคู่ | Object | [{tag: options.tagPrefix}] | อาร์เรย์ของวัตถุที่ใช้ในการจับคู่แท็ก |
| attrsparserrules | Object | {} | กฎเพิ่มเติมสำหรับแอตทริบิวต์ปลั๊กอิน Parser |
| เข้มงวด | Boolean | true | สลับการโยนข้อยกเว้น |
| Mergecustomizer | Function | function | การโทรกลับสำหรับ Lodash mergeWith เพื่อรวม options.expressions.locals และอุปกรณ์ประกอบฉาก |
| ระบบสาธารณูปโภค | Object | {merge: _.mergeWith, template: _.template} | วิธีการยูทิลิตี้ส่งผ่านไปยัง <script props> |
| Elementattributes | Object | {} | วัตถุที่มีชื่อแท็กและตัวดัดแปลงฟังก์ชั่นของ valid-attributes.js |
| Safelistattributes | String[] | ['data-*'] | อาร์เรย์ของชื่อแอตทริบิวต์เพื่อเพิ่มแอตทริบิวต์ที่ถูกต้องเริ่มต้น |
| blocklistattributes | String[] | [] | อาร์เรย์ของชื่อแอตทริบิวต์เพื่อลบออกจากแอตทริบิวต์ที่ถูกต้องเริ่มต้น |
สร้างส่วนประกอบ:
<!-- src/button.html -->
< button type =" button " class =" btn " >
< yield > </ yield >
</ button >ใช้:
<!-- src/index.html -->
< html >
< body >
< x-button type =" submit " class =" btn-primary " > Submit </ x-button >
</ body >
</ html >init posthtml:
// index.js
const posthtml = require ( 'posthtml' )
const components = require ( 'posthtml-component' )
const { readFileSync , writeFileSync } = require ( 'node:fs' )
posthtml ( [
components ( { root : './src' } )
] )
. process ( readFileSync ( 'src/index.html' , 'utf8' ) )
. then ( result => writeFileSync ( 'dist/index.html' , result . html , 'utf8' ) )ผลลัพธ์:
<!-- dist/index.html -->
< html >
< body >
< button type =" submit " class =" btn btn-primary " > Submit </ button >
</ body >
</ html > คุณอาจสังเกตเห็นว่าส่วนประกอบ src/button.html มีแอตทริบิวต์ type และ class และเราก็ผ่านแอตทริบิวต์เหล่านั้นเมื่อเราใช้มันใน src/index.html
ผลที่ได้คือ type นั้นถูกแทนที่และ class ถูกรวมเข้าด้วยกัน
โดยค่าเริ่มต้นแอตทริบิวต์ class และ style จะถูกรวมเข้าด้วยกันในขณะที่แอตทริบิวต์อื่น ๆ ทั้งหมดจะถูกแทนที่ นอกจากนี้คุณยังสามารถแทนที่คุณลักษณะ class และ style โดยการแทนที่ override: ไปยังแอตทริบิวต์คลาส
ตัวอย่างเช่น:
< x-button override:class =" btn-custom " > Submit </ x-button >
<!-- Output -->
< button type =" button " class =" btn-custom " > Submit </ button > แอตทริบิวต์ทั้งหมดที่คุณส่งผ่านไปยังส่วนประกอบจะถูกเพิ่มลงในโหนดแรกของส่วนประกอบของคุณหรือไปยังโหนดที่มี attributes ชื่อแอตทริบิวต์ เฉพาะ ในกรณีที่พวกเขาไม่ได้กำหนดเป็น props ผ่าน <script props> หรือหากไม่ได้เป็น "แอตทริบิวต์ที่รู้จัก"
นอกจากนี้คุณยังสามารถกำหนดคุณลักษณะใดที่ถือว่าถูกต้องผ่านตัวเลือกของปลั๊กอิน
รายละเอียดเพิ่มเติมเกี่ยวกับเรื่องนี้ในส่วนแอตทริบิวต์
แท็ก <yield> เป็นที่ที่เนื้อหาที่คุณส่งไปยังส่วนประกอบจะถูกฉีด
ปลั๊กอินกำหนดค่าตัวแยกวิเคราะห์ posthtml เพื่อรับรู้แท็กปิดการปิดตัวเองดังนั้นคุณยังสามารถเขียนได้คือ <yield />
เพื่อความกะทัดรัดเราจะใช้แท็กปิดตัวเองในตัวอย่าง
โดยค่าเริ่มต้นปลั๊กอินจะค้นหาส่วนประกอบที่มีส่วนขยาย .html คุณสามารถเปลี่ยนสิ่งนี้ได้โดยผ่านอาร์เรย์ของส่วนขยายไปยังตัวเลือก fileExtension
เมื่อใช้อาร์เรย์หากสองไฟล์ที่มีชื่อเดียวกันตรงกับทั้งส่วนขยายไฟล์จะใช้ส่วนขยายแรกในอาร์เรย์
const posthtml = require ( 'posthtml' )
const components = require ( 'posthtml-component' )
posthtml ( [
components ( {
root : './src' , // contains layout.html and layout.md
fileExtension : [ 'html' , 'md' ]
} )
] )
. process ( `<x-layout />` )
. then ( result => console . log ( result . html ) ) // layout.html content ดูเพิ่มเติมที่โฟลเดอร์ docs-src ที่คุณสามารถหาตัวอย่างเพิ่มเติมได้
คุณสามารถโคลน repo นี้และเรียกใช้ npm run build เพื่อรวบรวมพวกเขา
คุณสามารถใช้ส่วนประกอบได้หลายวิธีหรือการรวมกันของพวกเขา
หากคุณต้องการใช้ส่วนประกอบเป็น 'รวม' คุณสามารถกำหนดชื่อแท็กและชื่อแอตทริบิวต์ src
ใช้ตัวอย่างองค์ประกอบปุ่มก่อนหน้าของเราเราสามารถกำหนดชื่อแท็กและแอตทริบิวต์จากนั้นใช้เช่นนี้:
init posthtml:
// index.js
require ( 'posthtml' ) (
require ( 'posthtml-component' ) ( {
root : './src' ,
tag : 'component' ,
attribute : 'src'
} ) )
. process ( /* ... */ )
. then ( /* ... */ ) หากคุณต้องการการควบคุมการจับคู่แท็กเพิ่มเติมคุณอาจผ่านอาร์เรย์ของตัวจับคู่หรือวัตถุเดียวผ่าน options.matcher :
// index.js
const options = {
root : './src' ,
matcher : [
{ tag : 'a-tag' } ,
{ tag : 'another-one' } ,
{ tag : new RegExp ( `^app-` , 'i' ) } ,
]
} ;
require ( 'posthtml' ) ( require ( 'posthtml-component' ) ( options ) )
. process ( /* ... */ )
. then ( /* ... */ ) ด้วย posthtml-components คุณไม่จำเป็นต้องระบุชื่อพา ธ เมื่อคุณใช้ไวยากรณ์ x-tag-name
การตั้งค่า posthtml:
// index.js
const options = {
root : './src' ,
tagPrefix : 'x-'
} ;
require ( 'posthtml' ) ( require ( 'posthtml-component' ) ( options ) )
. process ( /* ... */ )
. then ( /* ... */ )ใช้:
<!-- src/index.html -->
< html >
< body >
< x-button > Submit </ x-button >
</ body >
</ html > หากส่วนประกอบของคุณอยู่ในโฟลเดอร์ย่อยคุณสามารถใช้ dot เพื่อเข้าถึง:
<!-- src/components/forms/button.html -->
< x-forms .button > Submit </ x-forms .button > หากส่วนประกอบของคุณอยู่ในโฟลเดอร์ย่อยที่มีหลายไฟล์ดังนั้นเพื่อหลีกเลี่ยงการเขียนชื่อไฟล์หลักคุณสามารถใช้ index.html โดยไม่ระบุ
นี่คือตัวอย่าง:
<!-- src/components/modals/index.html -->
< x-modal .index > Submit </ x-modal .index >
<!-- You may omit "index" part since the file is named "index.html" -->
< x-modal > Submit </ x-modal > คุณสามารถส่งผ่านตัวเลือกไปยัง posthtml-parser ผ่าน options.parserOptions
// index.js
const options = {
root : './src' ,
parserOptions : { decodeEntities : true }
} ;
require ( 'posthtml' ) ( require ( 'posthtml-component' ) ( options ) )
. process ( 'some HTML' , options . parserOptions )
. then ( /* ... */ ) สำคัญ
parserOptions ที่คุณส่งไปยังปลั๊กอินจะต้องส่งผ่านในวิธี process ในรหัสของคุณมิฉะนั้นการสร้าง posthtml ของคุณจะใช้ค่าเริ่มต้น posthtml-parser และจะแทนที่ทุกสิ่งที่คุณผ่านไปยัง posthtml-component
ปลั๊กอินรองรับแท็กปิดตัวเองตามค่าเริ่มต้น แต่คุณต้องตรวจสอบให้แน่ใจว่าได้เปิดใช้งานในวิธี process ในรหัสของคุณด้วยโดยผ่านการ recognizeSelfClosing: true ในวัตถุตัวเลือก:
// index.js
require ( 'posthtml' ) ( require ( 'posthtml-component' ) ( { root : './src' } ) )
. process ( 'your HTML...' , { recognizeSelfClosing : true } )
. then ( /* ... */ ) หากคุณไม่ได้เพิ่มสิ่งนี้ลงใน process PostTHTML จะใช้ค่าเริ่มต้น posthtml-parser และจะไม่รองรับแท็กส่วนประกอบปิดด้วยตนเอง ซึ่งจะส่งผลให้ทุกอย่างหลังจากแท็กปิดตัวเองไม่ได้ถูกส่งออก
คุณสามารถควบคุมได้อย่างเต็มที่ว่าไฟล์ส่วนประกอบของคุณมีอยู่ เมื่อคุณตั้งค่าเส้นทางรูทฐานของส่วนประกอบของคุณแล้วคุณสามารถตั้งค่าหลายโฟลเดอร์
ตัวอย่างเช่นหากรูทของคุณคือ ./src แล้วคุณมีโฟลเดอร์หลายแห่งที่คุณมีส่วนประกอบของคุณตัวอย่างเช่น ./src/components components และ ./src/layouts layouts คุณสามารถตั้งค่าปลั๊กอินได้ด้านล่าง:
// index.js
const options = {
root : './src' ,
folders : [ 'components' , 'layouts' ]
} ;
require ( 'posthtml' ) ( require ( 'posthtml-component' ) ( options ) )
. process ( /* ... */ )
. then ( /* ... */ )ด้วยเนมสเปซคุณสามารถกำหนดเส้นทางรูทระดับบนสุดให้กับส่วนประกอบของคุณ
มันจะมีประโยชน์สำหรับการจัดการธีมที่กำหนดเองซึ่งคุณกำหนดรูทระดับบนสุดเฉพาะด้วยรูททางเลือกสำหรับเมื่อไม่พบส่วนประกอบและรูทที่กำหนดเองสำหรับการเอาชนะ
สิ่งนี้ทำให้เป็นไปได้ที่จะสร้างโครงสร้างโฟลเดอร์เช่นนี้:
src (โฟลเดอร์รูท)components (โฟลเดอร์สำหรับส่วนประกอบเช่น Modal, ปุ่ม ฯลฯ )layouts (โฟลเดอร์สำหรับส่วนประกอบเลย์เอาต์เช่นเค้าโครงฐานส่วนหัวส่วนท้าย ฯลฯ )theme-dark (โฟลเดอร์ Namespace สำหรับ Theme-Dark)components (โฟลเดอร์สำหรับส่วนประกอบสำหรับธีมมืด)layouts (โฟลเดอร์สำหรับส่วนประกอบเลย์เอาต์สำหรับธีมมืด)theme-light (โฟลเดอร์ Namespace สำหรับ Theme-Light)components (โฟลเดอร์สำหรับส่วนประกอบสำหรับธีมแสง)layouts (โฟลเดอร์สำหรับส่วนประกอบเลย์เอาต์สำหรับธีมมืด)custom (โฟลเดอร์ที่กำหนดเองสำหรับแทนที่ธีมเนมสเปซของคุณ)theme-dark (โฟลเดอร์ที่กำหนดเองสำหรับการแทนที่ Dark Theme)components (โฟลเดอร์สำหรับการแทนที่ส่วนประกอบของ Theme Dark)layouts (โฟลเดอร์สำหรับการแทนที่ส่วนประกอบเลย์เอาต์ของธีมมืด)theme-light (โฟลเดอร์ที่กำหนดเองสำหรับธีม Override Light)components (โฟลเดอร์สำหรับการแทนที่ส่วนประกอบของ Theme Dark)layouts (โฟลเดอร์สำหรับการแทนที่ส่วนประกอบเลย์เอาต์ของธีมมืด)และตัวเลือกจะเป็นเช่น:
// index.js
const options = {
// Root for component without namespace
root : './src' ,
// Folders is always appended in 'root' or any defined namespace's folders (base, fallback or custom)
folders : [ 'components' , 'layouts' ] ,
namespaces : [ {
// Namespace name will be prepended to tag name (example <x-theme-dark::button>)
name : 'theme-dark' ,
// Root of the namespace
root : './src/theme-dark' ,
// Fallback root when a component is not found in namespace
fallback : './src' ,
// Custom root for overriding, the lookup happens here first
custom : './src/custom/theme-dark'
} , {
// Light theme
name : 'theme-light' ,
root : './src/theme-light' ,
fallback : './src' ,
custom : './src/custom/theme-light'
} , {
/* ... */
} ]
} ;ใช้เนมสเปซส่วนประกอบ:
<!-- src/index.html -->
< html >
< body >
< x-theme-dark : :button >Submit</ theme-dark : :button >
< x-theme-light : :button >Submit</ theme-light : :button >
</ body >
</ html >ส่วนประกอบอาจกำหนดช่องที่สามารถเติมเต็มเนื้อหาเมื่อใช้
ตัวอย่างเช่น:
<!-- src/modal.html -->
< div class = " modal " >
< div class = " modal-header " >
< slot : header />
</ div >
< div class = " modal-body " >
< slot : body />
</ div >
< div class = " modal-footer " >
< slot : footer />
</ div >
</ div >ใช้ส่วนประกอบ:
<!-- src/index.html -->
< x-modal >
< fill : header >Header content</ fill : header >
< fill : body >Body content</ fill : body >
< fill : footer >Footer content</ fill : footer >
</ x-modal >ผลลัพธ์:
<!-- dist/index.html -->
< div class =" modal " >
< div class =" modal-header " >
Header content
</ div >
< div class =" modal-body " >
Body content
</ div >
< div class =" modal-footer " >
Footer content
</ div >
</ div >โดยค่าเริ่มต้นเนื้อหาสล็อตจะถูกแทนที่ แต่คุณยังสามารถเติมเต็มหรือผนวกเนื้อหาหรือเก็บเนื้อหาเริ่มต้นโดยไม่กรอกช่อง
เพิ่มเนื้อหาเริ่มต้นในส่วนประกอบ:
<!-- src/modal.html -->
< div class = " modal " >
< div class = " modal-header " >
< slot : header >Default header</ slot : header >
</ div >
< div class = " modal-body " >
< slot : body >content</ slot : body >
</ div >
< div class = " modal-footer " >
< slot : footer >Footer</ slot : footer >
</ div >
</ div > <!-- src/index.html -->
< x-modal >
< fill : body prepend>Prepend body</ fill : body >
< fill : footer append>content</ fill : footer >
</ x-modal >ผลลัพธ์:
<!-- dist/index.html -->
< div class =" modal " >
< div class =" modal-header " >
Default header
</ div >
< div class =" modal-body " >
Prepend body content
</ div >
< div class =" modal-footer " >
Footer content
</ div >
</ div >คุณสามารถผลักดันเนื้อหาไปยังสแต็คที่มีชื่อซึ่งสามารถแสดงผลได้ที่อื่นเช่นในองค์ประกอบอื่น สิ่งนี้มีประโยชน์อย่างยิ่งสำหรับการระบุ JavaScript หรือ CSS ที่ต้องการโดยส่วนประกอบของคุณ
ก่อนอื่นให้เพิ่มแท็ก <stack> ลงใน HTML ของคุณ:
<!-- src/index.html -->
<html>
<head>
+ <stack name="styles" />
</head>
<body>
<x-modal>
<fill:header>Header content</fill:header>
<fill:body>Body content</fill:body>
<fill:footer>Footer content</fill:footer>
</x-modal>
+ <stack name="scripts" />
</body>
</html>จากนั้นในส่วนประกอบโมดอลหรือส่วนประกอบเด็กอื่น ๆ คุณสามารถผลักดันเนื้อหาไปยังสแต็กนี้:
<!-- src/modal.html -->
< div class = " modal " >
< div class = " modal-header " >
< slot : header />
</ div >
< div class = " modal-body " >
< slot : body />
</ div >
< div class = " modal-footer " >
< slot : footer />
</ div >
</ div >
< push name = " styles " >
< link href = " https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css " rel = " stylesheet " >
</ push >
< push name = " scripts " >
< script src = " https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js " ></ script >
</ push >ผลลัพธ์จะเป็น:
<!-- dist/index.html -->
< html >
< head >
< link href =" https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css " rel =" stylesheet " >
</ head >
< body >
< div class =" modal " >
< div class =" modal-header " >
Header content
</ div >
< div class =" modal-body " >
Body content
</ div >
< div class =" modal-footer " >
Footer content
</ div >
</ div >
< script src =" https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js " > </ script >
</ body >
</ html > แอตทริบิวต์ once ช่วยให้คุณสามารถผลักดันเนื้อหาเพียงครั้งเดียวต่อรอบการเรนเดอร์
ตัวอย่างเช่นหากคุณแสดงส่วนประกอบที่กำหนดภายในลูปคุณอาจต้องการผลักดัน JavaScript และ CSS ในครั้งแรกที่ส่วนประกอบจะแสดงผล
ตัวอย่าง.
<!-- src/modal.html -->
< div class =" modal " >
<!-- ... -->
</ div >
<!-- The push content will be pushed only once in the stack -->
< push name =" styles " once >
< link href =" https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css " rel =" stylesheet " >
</ push >
< push name =" scripts " once >
< script src =" https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js " > </ script >
</ push > โดยค่าเริ่มต้นเนื้อหาจะถูกผลักในสแต็กในลำดับที่กำหนด หากคุณต้องการรวมเนื้อหาเข้าสู่จุดเริ่มต้นของสแต็กคุณสามารถใช้แอตทริบิวต์ prepend :
< push name =" scripts " >
<!-- This will be second -->
< script src =" /example.js " > </ script >
</ push >
<!-- Later... -->
< push name =" scripts " prepend >
<!-- This will be first -->
< script src =" /example-2.js " > </ script >
</ push > props สามารถส่งผ่านไปยังส่วนประกอบในแอตทริบิวต์ HTML ในการใช้พวกเขาในส่วนประกอบพวกเขาจะต้องถูกกำหนดในแท็ก <script props> ของส่วนประกอบ
ตัวอย่างเช่น:
<!-- src/alert.html -->
< script props >
module . exports = {
title : props . title || 'Default title'
}
</ script >
< div >
{{ title }}
</ div >ใช้:
< x-alert title =" Hello world! " />ผลลัพธ์จะเป็น:
< div >
Hello world!
</ div > หากไม่มีแอตทริบิวต์ title ถูกส่งผ่านไปยังส่วนประกอบค่าเริ่มต้นจะถูกใช้
< x-my-alert />ผลลัพธ์จะเป็น:
< div >
Default title
</ div > ภายใน <script props> คุณสามารถเข้าถึงอุปกรณ์ประกอบฉากที่ผ่านผ่านวัตถุที่มีชื่อว่า props
นี่คือตัวอย่างของสิ่งที่คุณสามารถทำได้:
<!-- src/modal.html -->
< script props >
module . exports = {
title : props . title || 'Default title' ,
size : props . size ? `modal- ${ props . size } ` : '' ,
items : Array . isArray ( props . items ) ? props . items . concat ( [ 'first' , 'second' ] ) : [ 'first' , 'second' ]
}
</ script >
< div class =" modal {{ size }} " >
< div class =" modal-header " >
{{ title }}
</ div >
< div class =" modal-body " >
< each loop =" item in items " > < span > {{ item }} </ span > </ each >
</ div >
</ div >ใช้:
< x-modal
size =" xl "
title =" My modal title "
items =' ["third", "fourth"] '
class =" modal-custom "
/>ผลลัพธ์จะเป็น:
< div class =" modal modal-custom modal-xl " >
< div class =" modal-header " >
My modal title
</ div >
< div class =" modal-body " >
< span > first </ span >
< span > second </ span >
< span > third </ span >
< span > fourth </ span >
</ div >
</ div > สังเกตว่าแอตทริบิวต์ class ที่เราส่งผ่านไปยังส่วนประกอบถูกรวมเข้ากับค่าแอตทริบิวต์ class ของโหนดแรกภายใน
คุณสามารถเปลี่ยนวิธีการรวมแอตทริบิวต์เข้ากับอุปกรณ์ประกอบฉากทั่วโลกที่กำหนดผ่านตัวเลือกโดยผ่านฟังก์ชั่นการโทรกลับ
โดยค่าเริ่มต้นอุปกรณ์ประกอบฉากทั้งหมดจะถูกกำหนดขอบเขตไปยังส่วนประกอบและไม่สามารถใช้ได้กับส่วนประกอบที่ซ้อนกัน อย่างไรก็ตามคุณสามารถเปลี่ยนสิ่งนี้ตามความต้องการของคุณ
สร้างส่วนประกอบ:
<!-- src/child.html -->
< script props >
module . exports = {
title : props . title || 'Default title'
}
</ script >
< div >
Prop in child: {{ title }}
</ div > สร้างส่วนประกอบ <x-parent> ที่ใช้ <x-child> ::
<!-- src/parent.html -->
< script props >
module . exports = {
title : props . title || 'Default title'
}
</ script >
< div >
Prop in parent: {{ title }}
< x-child />
</ div >ใช้:
< x-parent title =" My title " />ผลลัพธ์จะเป็น:
< div >
Prop in parent: My title
< div >
Prop in child: Default title
</ div >
</ div > อย่างที่คุณเห็น title ใน <x-child> ส่วนประกอบทำให้ค่าเริ่มต้นและไม่ใช่ชุดที่ตั้งค่าผ่าน <x-parent>
ในการเปลี่ยนแปลงสิ่งนี้เราต้องรับ aware: ไปยังชื่อแอตทริบิวต์เพื่อส่งผ่านอุปกรณ์ประกอบฉากไปยังส่วนประกอบที่ซ้อนกัน
< x-parent aware:title =" My title " />เอาต์พุตตอนนี้จะเป็น:
< div >
Prop in parent: My title
< div >
Prop in child: My title
</ div >
</ div > คุณสามารถส่งผ่านแอตทริบิวต์ใด ๆ ไปยังส่วนประกอบของคุณและพวกเขาจะถูกเพิ่มลงในโหนดแรกของส่วนประกอบของคุณหรือไปยังโหนดที่มีแอตทริบิวต์ชื่อ attributes
หากคุณคุ้นเคยกับ vue.js นี่เป็นเช่นเดียวกับแอตทริบิวต์ Fallthrough ที่เรียกว่า หรือด้วย Laravel Blade มันเป็นส่วนประกอบ-attributes
โดยค่าเริ่ม class และ style จะถูกรวมเข้ากับ class และแอตทริบิวต์ style ที่มีอยู่ แอตทริบิวต์อื่น ๆ ทั้งหมดจะถูกแทนที่โดยค่าเริ่มต้น
หากคุณผ่านแอตทริบิวต์ที่กำหนดเป็น prop มันจะไม่ถูกเพิ่มลงในโหนดของส่วนประกอบ
นี่คือตัวอย่าง:
<!-- src/button.html -->
< script props >
module . exports = {
label : props . label || 'A button'
}
</ script >
< button type =" button " class =" btn " >
{{ label }}
</ button >ใช้ส่วนประกอบ:
<!-- src/index.html -->
< x-button type =" submit " class =" btn-primary " label =" My button " />ผลลัพธ์:
<!-- dist/index.html -->
< button type =" submit " class =" btn btn-primary " > My button </ button > หากคุณต้องการแทนที่ค่า class และ style แอตทริบิวต์ (แทนที่จะรวมเข้าด้วยกัน) เพียงแค่ชำระเงิน override: ไปยังชื่อแอตทริบิวต์:
<!-- src/index.html -->
< x-button type =" submit " override:class =" btn-custom " label =" My button " />ผลลัพธ์:
<!-- dist/index.html -->
< button type =" submit " class =" btn-custom " > My button </ button > หากคุณต้องการให้แอตทริบิวต์ผ่านไปยังโหนดที่แน่นอนให้ใช้แอตทริบิวต์ attributes :
<!-- src/my-component.html -->
< div class =" first-node " >
< div class =" second-node " attributes >
Hello world!
</ div >
</ div >ใช้ส่วนประกอบ:
<!-- src/index.html -->
< x-my-component class =" my-class " />ผลลัพธ์:
<!-- dist/index.html -->
< div class =" first-node " >
< div class =" second-node my-class " >
Hello world!
</ div >
</ div >คุณสามารถเพิ่มกฎที่กำหนดเองเพื่อกำหนดวิธีการแยกวิเคราะห์แอตทริบิวต์-เราใช้ Posthtml-Attrs-Parser เพื่อจัดการกับพวกเขา
หากการกำหนดค่าเริ่มต้นสำหรับแอตทริบิวต์ที่ถูกต้องไม่เหมาะสำหรับคุณคุณสามารถกำหนดค่าตามที่อธิบายไว้ด้านล่าง
// index.js
const { readFileSync , writeFileSync } = require ( 'fs' )
const posthtml = require ( 'posthtml' )
const components = require ( 'posthtml-component' )
const options = {
root : './src' ,
// Add attributes to specific tag or override defaults
elementAttributes : {
DIV : ( defaultAttributes ) => {
/* Add new one */
defaultAttributes . push ( 'custom-attribute-name' ) ;
return defaultAttributes ;
} ,
DIV : ( defaultAttributes ) => {
/* Override all */
defaultAttributes = [ 'custom-attribute-name' , 'another-one' ] ;
return defaultAttributes ;
} ,
} ,
// Add attributes to all tags, use '*' as wildcard for attribute name that starts with
safelistAttributes : [
'custom-attribute-name' ,
'attribute-name-start-with-*'
] ,
// Remove attributes from all tags that support it
blocklistAttributes : [
'role'
]
}
posthtml ( components ( options ) )
. process ( readFileSync ( 'src/index.html' , 'utf8' ) )
. then ( result => writeFileSync ( 'dist/index.html' , result . html , 'utf8' ) ) คุณสามารถทำงานกับ <slot> และ <fill> หรือคุณสามารถสร้างส่วนประกอบสำหรับแต่ละบล็อกของส่วนประกอบของคุณและคุณยังสามารถรองรับทั้งสองอย่าง
คุณสามารถค้นหาตัวอย่างของสิ่งนี้ภายใน docs-src/components/modal ต่อไปนี้เป็นคำอธิบายสั้น ๆ ของทั้งสองวิธี
สมมติว่าเราต้องการสร้างส่วนประกอบสำหรับ Bootstrap Modal
รหัสที่ต้องการคือ:
<!-- Modal HTML -->
< div class =" modal fade " id =" exampleModal " tabindex =" -1 " aria-labelledby =" exampleModalLabel " aria-hidden =" true " >
< div class =" modal-dialog " >
< div class =" modal-content " >
< div class =" modal-header " >
< h1 class =" modal-title fs-5 " id =" exampleModalLabel " > Modal title </ h1 >
< button type =" button " class =" btn-close " data-bs-dismiss =" modal " aria-label =" Close " > </ button >
</ div >
< div class =" modal-body " >
...
</ div >
< div class =" modal-footer " >
< button type =" button " class =" btn btn-secondary " data-bs-dismiss =" modal " > Close </ button >
< button type =" button " class =" btn btn-primary " > Save changes </ button >
</ div >
</ div >
</ div >
</ div >มีรหัสเกือบสามบล็อก: ส่วนหัวร่างกายและส่วนท้าย
ดังนั้นเราสามารถสร้างส่วนประกอบที่มีสามช่อง:
<!-- Modal component -->
<div class="modal fade" tabindex="-1" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
- <h1 class="modal-title fs-5" id="exampleModalLabel">Modal title</h1>
+ <slot:header />
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
+ <slot:body />
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
+ <slot:footer />
- <button type="button" class="btn btn-primary">Save changes</button>
</div>
</div>
</div>
</div>จากนั้นเราสามารถใช้มันได้เช่นนี้:
< x-modal
id =" exampleModal "
aria-labelledby =" exampleModalLabel "
>
< slot:header >
< h5 class =" modal-title " id =" exampleModalLabel " > My modal </ h5 >
</ slot:header >
< slot:body >
Modal body content goes here...
</ slot:body >
< slot:footer close =" false " >
< button type =" button " class =" btn btn-primary " > Confirm </ button >
</ slot:footer >
</ x-modal >อีกวิธีหนึ่งคือการแยกส่วนประกอบเป็นส่วนประกอบที่เล็กลงผ่านแอตทริบิวต์ไปยังแต่ละรายการ
ดังนั้นเราจึงสร้างองค์ประกอบหลักและจากนั้นส่วนประกอบเล็ก ๆ ที่แตกต่างกันสามชิ้น:
<!-- Main modal component -->
< div class =" modal fade " tabindex =" -1 " aria-hidden =" true " >
< div class =" modal-dialog " >
< div class =" modal-content " >
< yield />
</ div >
</ div >
</ div > <!-- Header modal component -->
< div class =" modal-header " >
< yield />
</ div > <!-- Body modal component -->
< div class =" modal-body " >
< yield />
</ div > <!-- Footer modal component -->
< div class =" modal-footer " >
< yield />
</ div >จากนั้นคุณสามารถใช้มันได้เช่นนี้:
< x-modal
id =" exampleModal "
aria-labelledby =" exampleModalLabel "
>
< x-modal .header >
< h5 class =" modal-title " id =" exampleModalLabel " > My modal </ h5 >
</ x-modal .header >
< x-modal .body >
Modal body content goes here...
</ x-modal .body >
< x-modal .footer >
< button type =" button " class =" btn btn-primary " > Confirm </ button >
</ x-modal .footer >
</ x-modal >ดังที่ได้กล่าวไว้ในวิธีนี้คุณสามารถส่งผ่านแอตทริบิวต์ให้กับแต่ละคนโดยไม่ต้องกำหนดอุปกรณ์ประกอบฉาก
นอกจากนี้คุณยังสามารถรวมทั้งสองวิธีแล้วใช้กับสล็อตหรือส่วนประกอบเล็ก ๆ :
<!-- Modal -->
< div
class =" modal fade "
tabindex =" -1 "
aria-hidden =" true "
aria-modal =" true "
role =" dialog "
>
< div class =" modal-dialog " >
< div class =" modal-content " >
< if condition =" $slots.header?.filled " >
< x-modal .header >
< slot:header />
</ x-modal .header >
</ if >
< if condition =" $slots.body?.filled " >
< x-modal .body >
< slot:body />
</ x-modal .body >
</ if >
< if condition =" $slots.footer?.filled " >
< x-modal .footer close =" {{ $slots.footer?.props.close }} " >
< slot:footer />
</ x-modal .footer >
</ if >
< yield />
</ div >
</ div > <!-- /.modal-dialog -->
</ div > <!-- /.modal -->ตอนนี้คุณสามารถใช้ส่วนประกอบของคุณกับสล็อตหรือส่วนประกอบเล็ก ๆ
ดังที่คุณอาจสังเกตเห็นโดยใช้สล็อตคุณสามารถใช้ส่วนประกอบเล็ก ๆ ของคุณได้แล้วและคุณยังสามารถผ่านอุปกรณ์ประกอบฉากผ่าน $slots ซึ่งมี props ประกอบฉากทั้งหมดผ่านสล็อตและตรวจสอบว่าช่องเต็มหรือไม่
หากคุณย้ายจาก posthtml-extend และ/หรือ posthtml-modules โปรดติดตามการอัปเดตที่นี่: posthtml-components/ปัญหา/16
ดูแนวทางและคู่มือการบริจาค Postthtml
ต้องขอบคุณผู้มีส่วนร่วม posthtml ทุกคนและโดยเฉพาะอย่างยิ่งกับผู้มีส่วนร่วม posthtml-extend และ posthtml-modules ซึ่งเป็นส่วนหนึ่งของรหัสคือ ถูกขโมย แรงบันดาลใจจากปลั๊กอินเหล่านี้ ขอขอบคุณอย่างมากสำหรับเครื่องยนต์เทมเพลต Laravel Blade