Pass Through 屬性是一種 API,用於存取元件的內部 DOM 結構。
在傳統的第三方 UI 函式庫中,使用者只能使用元件作者提供的 API。此 API 通常包含 props、事件和插槽。每當需要 API 中新的自訂選項時,元件作者都需要開發並發布新版本。
PrimeTek 的願景是你的元件,而不是我們的。pass through 功能是實現此願景的關鍵要素,透過公開元件內部結構,以便將任意屬性和監聽器應用於 DOM 元素。這種方法的主要優點是,它讓您擺脫了主要元件 API 的限制。每當您需要自訂一個缺乏內建功能的元件以滿足您的特定需求時,我們建議您考慮使用 pass-through 功能。
PrimeTV YouTube 頻道上有兩個影片,第一個是簡介,第二個涵蓋了一個通過 pass-through 解決的獨特案例。
每個元件都有一個特殊的 pt 屬性,用於定義一個物件,其鍵對應於可用的 DOM 元素。每個值可以是字串、物件或函數,該函數返回字串或物件,以定義要應用於元素的任意屬性,例如樣式、aria、data-* 或自訂屬性。如果值是字串或返回字串的函數,則將其視為類別定義,並添加到元素的 class 屬性中。每個元件文件都有一個專門的章節,記錄透過 PT 公開的可用的區段名稱。
pt 最常見的用法是樣式和自訂。class 和 style 屬性支援 Vue 綁定(如陣列、物件和條件)的精確語法。下面的範例使用 PrimeFlex CSS 函式庫設定 Panel 元件的樣式。
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
<Panel header="Header" toggleable
:pt="{
header: (options) => ({
id: 'myPanelHeader',
style: {
'user-select': 'none'
},
class: [
'border-primary',
{
'bg-primary text-primary-contrast': options.state.d_collapsed,
'text-primary bg-primary-contrast': !options.state.d_collapsed
}
]
}),
content: { class: 'border-primary text-lg text-primary-700' },
title: 'text-xl', // OR { class: 'text-xl' }
toggler: () => 'bg-primary text-primary-contrast hover:text-primary hover:bg-primary-contrast' // OR { class: 'bg-primary text-primary-contrast hover:text-primary hover:bg-primary-contrast' }
}">
<p class="m-0">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
</p>
</Panel>
宣告式語法提供了一種替代程式化語法的方案。以 pt 開頭的屬性會根據以下格式由元件以不同的方式解釋。此外,還計劃開發一個 IDE 擴充功能,以便在未來自動完成這些值,以獲得更好的開發人員體驗。
<ComponentTag pt:[passthrough_key]:[attribute]="value" />
以下是另一個範例,針對相同的選項使用了兩種語法替代方案。
<Panel
:pt="{
root: {
class='"border-1 border-solid'
},
header: {
'data-test-id': 'testid',
class: 'bg-blue-500',
onClick: onHeaderClick
}
}"
>
<Panel
pt:root:class="border border-solid"
pt:header:id="headerId"
pt:header:data-test-id="testId"
pt:header:class="bg-blue-500"
:pt:header:onClick="onHeaderClick"
>
以 pc 為前綴的區段名稱表示 PrimeVue 元件,將它們與標準 DOM 元素區分開來,並表示需要巢狀結構。例如,"badge" 區段被識別為 pcBadge,因為按鈕元件在內部整合了 badge 元件。
<Button
type="button"
label="Messages"
icon="pi pi-inbox"
badge="2"
variant="outlined"
severity="secondary"
:pt="{
root: '!px-4 !py-3',
icon: '!text-xl !text-violet-500 dark:!text-violet-400',
label: '!text-lg !text-violet-500 dark:!text-violet-400',
pcBadge: {
root: '!bg-violet-500 dark:!bg-violet-400 !text-white dark:!text-black'
}
}"
/>
元件的生命週期掛鉤透過使用 hooks 屬性作為 pass through 公開,以便可以註冊回呼函式。可用的回呼函式有 onBeforeCreate、onCreated、onBeforeUpdate、onUpdated、onBeforeMount、onMounted、onBeforeUnmount 和 onUnmounted。有關生命週期掛鉤的詳細資訊,請參閱 Vue.js 文件。
<Panel header="Header" :pt="panelPT">
Content
</Panel>
定義每個元件類型的共用 pass through 屬性。例如,使用以下設定,所有面板標頭都具有 bg-primary 樣式類別,並且所有自動完成元件都具有固定寬度。這些設定可以被特定元件覆蓋,因為元件的 pt 屬性優先於全域 pt。
import { createApp } from "vue";
import PrimeVue from "primevue/config";
const app = createApp(App);
app.use(PrimeVue, {
pt: {
panel: {
header: {
class: 'bg-primary text-primary-contrast'
}
},
autocomplete: {
input: {
root: 'w-64' // OR { class: 'w-64' }
}
}
}
});
global 屬性具有 css 選項,用於定義屬於全域 pt 設定的自訂 CSS。此功能的常見使用案例是定義與 pass through 設定相關的全域樣式和動畫。
import { createApp } from "vue";
import PrimeVue from "primevue/config";
const app = createApp(App);
app.use(PrimeVue, {
pt: {
global: {
css: `
.my-button {
border-width: 2px;
}
`
},
button: {
root: 'my-button'
}
}
});
使用 usePassThrough 公用程式自訂現有的 pass through 設定。第一個參數是要自訂的物件,第二個參數是自訂設定,最後一個參數是合併策略。
import { createApp } from "vue";
import PrimeVue from "primevue/config";
import { usePassThrough } from "primevue/passthrough";
import BasePreset from "./basepreset";
const app = createApp(App);
const CustomPreset = usePassThrough(
BasePreset,
{
panel: {
title: {
class: ['leading-none font-light text-2xl']
}
}
},
{
mergeSections: true,
mergeProps: false
}
);
app.use(PrimeVue, { unstyled: true, pt: CustomPreset });
mergeSections 定義是否新增主設定中的區段,而 mergeProps 控制是覆蓋還是合併定義的 props。mergeSections 的預設值為 true,mergeProps 的預設值為 false。
const CustomPreset = usePassThrough(
BasePreset,
{
panel: {
header: 'my_panel_header'
}
},
{ mergeSections: true, mergeProps: false }
);
// Output:
// panel.header.class => 'my_panel_header'
// panel.title.class => Tailwind.panel.title.class
const CustomPreset = usePassThrough(
BasePreset,
{
panel: {
header: 'my_panel_header'
}
},
{ mergeSections: true, mergeProps: true }
);
// Output:
// panel.header.class => [Tailwind.panel.header.class, 'my_panel_header']
// panel.title.class => Tailwind.panel.title.class
const CustomPreset = usePassThrough(
BasePreset,
{
panel: {
header: 'my_panel_header'
}
},
{ mergeSections: false, mergeProps: true }
);
// Output:
// panel.header.class => [Tailwind.panel.header.class, 'my_panel_header']
// panel.title.class => undefined
const CustomPreset = usePassThrough(
BasePreset,
{
panel: {
header: 'my_panel_header'
}
},
{ mergeSections: false, mergeProps: false }
);
// Output:
// panel.header.class => 'my_panel_header'
// panel.title.class => undefined