@blocklet/ui-react
Version:
Some useful front-end web components that can be used in Blocklets.
182 lines (146 loc) • 8.65 kB
Markdown
# ComponentInstaller
`ComponentInstaller` 是一個實用工具元件,對於依賴其他 blocklet 的功能扮演著守門員的角色。它會驗證指定的元件相依性是否已安裝。如果尚未安裝,它會為管理員(預設為 `owner` 或 `admin` 角色)提供一個使用者友善的介面,讓他們可以直接安裝。如果使用者缺乏必要的權限,它會顯示一則訊息,建議他們聯絡管理員。
此元件對於建立穩健的應用程式至關重要,能夠優雅地處理缺失的選用相依性,並透過引導管理員完成安裝過程來改善使用者體驗。
## 運作方式
該元件的邏輯遵循一個清晰的順序流程,以確保在渲染其子元件之前滿足所有相依性。
<!-- DIAGRAM_IMAGE_START:flowchart:4:3:1765962229 -->

<!-- DIAGRAM_IMAGE_END -->
1. **相依性檢查**:它會讀取 `did` prop,並對照 blocklet 的元資料(`window.blocklet.optionalComponents`)進行檢查,以確定所需元件是否已安裝。
2. **權限檢查**:如果有任何元件缺失,它會使用 `SessionPermission` 元件來驗證目前使用者的角色是否與 `roles` prop 中指定的角色相符。
3. **條件式渲染**:
* 如果所有相依性都已安裝,它會渲染其 `children`。
* 如果相依性缺失且使用者擁有權限,它會顯示一個彈出式安裝面板。
* 如果相依性缺失且使用者缺乏權限,它會顯示聯絡管理員的建議,或者在啟用 `noPermissionMute` 的情況下渲染一個 `fallback` 元件。
## 基本用法
將任何依賴選用 blocklet 的元件或功能用 `ComponentInstaller` 包裹起來。提供所需元件的 DID。
```jsx "MyFeature.jsx" icon=logos:react
import ComponentInstaller from '@arcblock/blocklet-ui-react/lib/ComponentInstaller';
import MyDependentComponent from './MyDependentComponent';
export default function MyFeature() {
// 請替換為所需元件的實際 DID
const requiredComponentDid = 'z8ia2427634f1e909a304e2b963715a18';
return (
<ComponentInstaller did={requiredComponentDid}>
{/* 只有在滿足相依性條件時,此元件才會被渲染 */}
<MyDependentComponent />
</ComponentInstaller>
);
}
```
## 屬性 (Props)
`ComponentInstaller` 接受以下屬性 (props) 來自訂其行為。
<x-field-group>
<x-field data-name="did" data-type="string | string[]" data-required="true">
<x-field-desc markdown>要檢查的元件相依性的 DID (或 DID 陣列)。這是您所需 blocklet 的主要識別碼。</x-field-desc>
</x-field>
<x-field data-name="children" data-type="any" data-required="true">
<x-field-desc markdown>一旦確認所有相依性都已安裝,要渲染的內容。可以是標準的 React 節點或渲染函數。</x-field-desc>
</x-field>
<x-field data-name="roles" data-type="string[]" data-default='["owner", "admin"]'>
<x-field-desc markdown>允許查看安裝 UI 並安裝缺失元件的使用者角色陣列。</x-field-desc>
</x-field>
<x-field data-name="fallback" data-type="React.ReactNode" data-required="false">
<x-field-desc markdown>一個備用元件,用於在檢查相依性期間,或當 `noPermissionMute` 對於沒有安裝權限的使用者啟用時顯示。</x-field-desc>
</x-field>
<x-field data-name="noPermissionMute" data-type="boolean" data-default="false">
<x-field-desc markdown>如果為 `true`,沒有權限的使用者將看到 `fallback` 元件(或什麼都不顯示),而不是「聯絡管理員」的訊息。</x-field-desc>
</x-field>
<x-field data-name="disabled" data-type="boolean" data-default="false">
<x-field-desc markdown>如果為 `true`,該元件會繞過所有檢查並立即渲染其 `children`。</x-field-desc>
</x-field>
<x-field data-name="onInstalled" data-type="function" data-required="false">
<x-field-desc markdown>在相依性檢查完成後觸發的回呼函數。它會接收已安裝元件的列表。</x-field-desc>
</x-field>
<x-field data-name="onError" data-type="function" data-required="false">
<x-field-desc markdown>如果在相依性檢查期間發生錯誤時觸發的回呼函數。它會接收導致錯誤的元件列表。</x-field-desc>
</x-field>
<x-field data-name="onClose" data-type="function" data-required="false">
<x-field-desc markdown>當安裝彈出視窗關閉時調用的回呼函數。</x-field-desc>
</x-field>
<x-field data-name="closeByOutSize" data-type="boolean" data-default="false">
<x-field-desc markdown>如果為 `true`,當使用者點擊安裝彈出視窗外部時,該視窗將會關閉。</x-field-desc>
</x-field>
<x-field data-name="warnIcon" data-type="React.ReactNode" data-required="false">
<x-field-desc markdown>一個自訂的 React 節點,用於替換安裝彈出視窗中的預設警告圖示。</x-field-desc>
</x-field>
</x-field-group>
## 進階用法
### 檢查多個元件
您可以將一個 DID 陣列傳遞給 `did` prop,以一次性檢查多個相依性。只有在所有指定的元件都已安裝的情況下,子元件才會被渲染。
```jsx "MyDashboard.jsx" icon=logos:react
import ComponentInstaller from '@arcblock/blocklet-ui-react/lib/ComponentInstaller';
import AnalyticsWidget from './AnalyticsWidget';
import CmsWidget from './CmsWidget';
export default function MyDashboard() {
const requiredDids = [
'z8ia2427634f1e909a304e2b963715a18', // 分析服務
'z8ia3c1f2e4b8e6a1b2c3d4e5f6a7b8c9', // 內容管理系統服務
];
return (
<ComponentInstaller did={requiredDids}>
<AnalyticsWidget />
<CmsWidget />
</ComponentInstaller>
);
}
```
### 使用備用元件處理載入狀態
提供一個 `fallback` 元件,以在相依性檢查進行中時改善使用者體驗。這對於搭配 `noPermissionMute` 為未經授權的使用者顯示佔位符也很有用。
```jsx "FeatureWithLoading.jsx" icon=logos:react
import ComponentInstaller from '@arcblock/blocklet-ui-react/lib/ComponentInstaller';
import CircularProgress from '@mui/material/CircularProgress';
import Box from '@mui/material/Box';
import MyDependentComponent from './MyDependentComponent';
export default function FeatureWithLoading() {
const LoadingSpinner = (
<Box sx={{ display: 'flex', justifyContent: 'center', p: 4 }}>
<CircularProgress />
</Box>
);
return (
<ComponentInstaller
did="z8ia2427634f1e909a304e2b963715a18"
fallback={LoadingSpinner}
noPermissionMute={true}
>
<MyDependentComponent />
</ComponentInstaller>
);
}
```
### 使用渲染屬性 (Render Props) 自訂 UI
為了完全控制 UI,您可以傳遞一個函數作為 `children`。此函數會接收一個包含 `hasPermission`、`optComponents` 和 `installStatus` 的物件,讓您可以建立完全自訂的安裝介面。
```jsx "CustomInstallerButton.jsx" icon=logos:react
import ComponentInstaller from '@arcblock/blocklet-ui-react/lib/ComponentInstaller';
import Button from '@mui/material/Button';
export default function CustomInstallerButton() {
const requiredDid = 'z8ia2427634f1e909a304e2b963715a18';
return (
<ComponentInstaller did={requiredDid}>
{({ hasPermission, optComponents, installStatus }) => {
const isMissing = optComponents.length > 0;
const status = installStatus[requiredDid] || 'not_installed';
if (!isMissing) {
return <p>功能已準備就緒!</p>;
}
if (!hasPermission) {
return <p>請要求管理員安裝所需元件。</p>;
}
return (
<Button
variant="contained"
disabled={status !== 'not_installed'}
onClick={() => window.open(optComponents[0].installUrl, '_blank')}
>
{status === 'not_installed' ? `安裝 ${optComponents[0].meta.title}` : `安裝中... (${status})`}
</Button>
);
}}
</ComponentInstaller>
);
}
```
## 總結
`ComponentInstaller` 是一個強大的元件,用於管理 blocklet 應用程式中的選用相依性。它提供了一種結構化且使用者友善的方式,以確保所需元件可用,並在必要時引導管理員完成安裝過程。透過使用此元件,您可以建立更具彈性、功能更豐富且能適應使用者環境的應用程式。
有關管理元件的更多詳細資訊,您可能也會對 [BlockletStudio](./components-component-management-blocklet-studio.md) 元件感興趣,它為資源和元件管理提供了更全面的介面。